Javaマルチスレッド(スレッド同期)
>スレッドセキュリティの問題
スレッドのセキュリティ問題の例は、銀行のお金の引き出し問題です.銀行がお金を引き出す基本的な流れは以下のステップに分けることができます.
ビジネス・プロセスは、単一スレッド環境では問題なく、マルチスレッドが同時に存在する場合に問題が発生する可能性があります.確率が現れるかもしれませんが、プログラムを100万回実行しても現れないかもしれませんが、問題がないわけではありません.
アカウントクラス:
public class Account {
private String userNo;
private double account;
public Account(String userNo,double account){
this.userNo = userNo;
this.account = account;
}
public String getUserNo() {
return userNo;
}
public void setUserNo(String userNo) {
this.userNo = userNo;
}
public double getAccount() {
return account;
}
public void setAccount(double account) {
this.account = account;
}
}
:
public class ATMThread extends Thread {
private Account account;
private double money;
public ATMThread(String atmNo, Account account, double money) {
super(atmNo);
this.account = account;
this.money = money;
}
public void run() {
if (this.account.getAccount() >= money) {
System.out.println(this.getName() + " ATM ! :" + this.money);
//
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//
this.account.setAccount(account.getAccount() - money);
System.out.println(" :" + account.getAccount());
}else{
System.out.println(" !");
}
}
public static void main(String[] args) {
Account account=new Account("12345", 1000);
//
new ATMThread("0001", account, 800).start();
new ATMThread("0002", account, 800).start();
}
}
:
0001 ATM ! :800.0
0002 ATM ! :800.0
:200.0
:-600.0
0001 ATM ! :800.0
0002 ATM ! :800.0
:200.0
:200.0
0001 ATM ! :800.0
0002 ATM ! :800.0
:-600.0
:-600.0
, 1000 1600 , , 。
, 。
>
, run() —— Account , Account , 。
,Java , 。 :
synchronized(obj){
// }
obj , : , 。
Java , : , 。 , account , :
public class ATMThread extends Thread {
private Account account;
private double money;
public ATMThread(String atmNo, Account account, double money) {
super(atmNo);
this.account = account;
this.money = money;
}
public void run() {
synchronized (account) {
if (this.account.getAccount() >= money) {
System.out.println(this.getName() + " ATM ! :" + this.money);
//
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//
this.account.setAccount(account.getAccount() - money);
System.out.println(" :" + account.getAccount());
}else{
System.out.println(" !");
}
}
}
public static void main(String[] args) {
Account account=new Account("12345", 1000);
//
new ATMThread("0001", account, 800).start();
new ATMThread("0002", account, 800).start();
}
}
:
0001 ATM ! :800.0
:200.0
!
synchronized run() , account , :
“ >> >> ” , , , , , 。 ( ), , 。
> :
synchronized 。 , , this, 。
, :
- 。
- 。
- , 。
( ) , , ; 。 Accout , userNo account , Account account , 。 Account account , account 。
public class Account {
private String userNo;
private double account;
public Account(String userNo,double account){
this.userNo = userNo;
this.account = account;
}
public synchronized void drawMoney(double money){
if (this.account >= money) {
System.out.println(this.userNo + " ATM ! :" + money);
//
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//
this.account=this.account - money;
System.out.println(" :" + account);
}else{
System.out.println(" !");
}
}
}
:
public class ATMThread extends Thread {
private Account account;
private double money;
public ATMThread(String atmNo, Account account, double money) {
super(atmNo);
this.account = account;
this.money = money;
}
public void run() {
account.drawMoney(money);
}
public static void main(String[] args) {
Account account = new Account("12345", 1000);
//
new ATMThread("0001", account, 800).start();
new ATMThread("0002", account, 800).start();
}
}
:
12345 ATM ! :800.0
:200.0
!
TestThread , Account drawMoney , synchronized , 。 account , , —— —— 。
:
- synchronized , , 、 。
- , 。
- , , Accout userNo 。
- , , : 。
>
、 , , ? 。
:
- 、 , 。
- 、 break、return 、 , 。
- 、 Error Exception, 、 , 。
- , wait() , , 。
, :
- , Thread.sleep()、Thread.yield() , 。
- , suspend() , 。
, sleep:
public class TestThread extends Thread {
private TestOne test;
public TestThread(String name,TestOne test){
super(name);
this.test = test;
}
@Override
public void run() {
this.test.show();
}
public static void main(String[] args) {
TestOne one = new TestOne();
TestThread thread = new TestThread(" 1",one);
TestThread thread1 = new TestThread(" 2",one);
thread1.start();
thread.start();
}
}
class TestOne{
public synchronized void show(){
for(int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
> (Lock)
Java5 ,Java —— , , Lock 。
Lock synchronized synchronized ,Lock , , Condition 。
Lock 。 , , Lock , Lock 。
, ReadWriteLock 。Lock、ReadWriteLock Java5 , Lock ReentrantLock , ReadWriteLock ReentrantReadWriteLock 。
, ReentrantLock, Lock 、 。 :
public class A {
private final ReentrantLock lock = new ReentrantLock();
public void method() {
//
lock.lock();
try {
//
} finally {
//
lock.unlock();
}
}
}
ReentrantLock , , finally 。 ReentrantLock , Account , :
public class Account {
private String userNo;
private double account;
public Account(String userNo,double account){
this.userNo = userNo;
this.account = account;
}
public synchronized void drawMoney(double money){
ReentrantLock lock=new ReentrantLock();
lock.lock();
try {
if (this.account >= money) {
System.out.println(this.userNo + " ATM ! :" + money);
//
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//
this.account=this.account - money;
System.out.println(" :" + account);
}else{
System.out.println(" !");
}
}finally{
lock.unlock();
}
}
}
、 , , , , 。
, , 。Lock , tryLock() , LockInterruptibly() , tryLock(long time,TimeUnit unit) 。
ReentrantLock , ReentrantLock ,ReentrantLock lock() , lock() , unlock() , 。
public class TestThread extends Thread {
private TestOne one;
public TestThread(String name, TestOne one) {
super(name);
this.one = one;
}
@Override
public void run() {
this.one.show1();
}
public static void main(String[] args) {
TestOne one = new TestOne();
TestThread th1 = new TestThread(" 1", one);
TestThread th2 = new TestThread(" 2", one);
th1.start();
th2.start();
}
}
class TestOne {
private final ReentrantLock lock = new ReentrantLock();
public void show1() {
lock.lock();
try {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + "show1 " + i);
if (i == 10) {
this.show2();
}
}
} finally {
lock.unlock();
}
}
private void show2() {
lock.lock();
try {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + "show2 " + i);
}
} finally {
lock.unlock();
}
}
}
:
2show1 0
2show1 1
2show1 2
2show1 3
2show1 4
2show1 5
2show1 6
2show1 7
2show1 8
2show1 9
2show1 10
2show2 0
2show2 1
2show2 2
2show2 3
2show2 4
2show2 5
2show2 6
2show2 7
2show2 8
2show2 9
2show2 10
2show2 11
2show2 12
2show2 13
2show2 14
2show2 15
2show2 16
2show2 17
2show2 18
2show2 19
2show1 11
2show1 12
2show1 13
2show1 14
2show1 15
2show1 16
2show1 17
2show1 18
2show1 19
1show1 0
1show1 1
1show1 2
1show1 3
1show1 4
1show1 5
1show1 6
1show1 7
1show1 8
1show1 9
1show1 10
1show2 0
1show2 1
1show2 2
1show2 3
1show2 4
1show2 5
1show2 6
1show2 7
1show2 8
1show2 9
1show2 10
1show2 11
1show2 12
1show2 13
1show2 14
1show2 15
1show2 16
1show2 17
1show2 18
1show2 19
1show1 11
1show1 12
1show1 13
1show1 14
1show1 15
1show1 16
1show1 17
1show1 18
1show1 19
: ReentrantLock , , 。
> :
,Java , , 。 , , , , 。
, , 。
, ,A A , B B , A B , B B , B A , A A 。 。
public class Dead implements Runnable{
boolean flag;
public static Object o1=new Object();//
public static Object o2=new Object();
public Dead(boolean flag) {
this.flag=flag;
}
@Override
public void run() {
if (flag) {
synchronized (o1) {
System.out.println(Thread.currentThread().getName()+" o1");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" o1 o2");
synchronized (o2) {// o1 , o1, o2
}
}
}else{
synchronized (o2) {
System.out.println(Thread.currentThread().getName()+" o2");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" o2 o1");
synchronized (o1) { // o2 , o2, o1
}
}
}
}
public static void main(String[] args) {
Dead d=new Dead(false);
Dead d2=new Dead(true);
new Thread(d).start();
new Thread(d2).start();
}
}
:
Thread-1 o1
Thread-0 o2
Thread-0 o2 o1
Thread-1 o1 o2
:
public class DeadThread implements Runnable {
private A a = new A();
private B b = new B();
public void init(){
Thread.currentThread().setName(" ");
a.a1(b);
}
@Override
public void run() {
Thread.currentThread().setName(" ");
b.b1(a);//1
}
public static void main(String[] args) {
DeadThread dt = new DeadThread();
new Thread(dt).start();
dt.init();
}
}
class A{
public synchronized void a1(B b){
System.out.println(" :"+Thread.currentThread().getName()+" A a1 ");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" :"+Thread.currentThread().getName()+" B last ");
b.last();
}
public synchronized void last(){
System.out.println(" A last !");
}
}
class B{
public synchronized void b1(A a){
System.out.println(" :"+Thread.currentThread().getName()+" B b1 ");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" :"+Thread.currentThread().getName()+" A last ");
a.last();
}
public synchronized void last(){
System.out.println(" B last !");
}
}
:
: A a1
: B b1
: B last
: A last
—— a1 , a —— ——
—— b1 , b —— ——
—— b last , b , b ——
—— a last , a , a ——
。
Thread suspend() , Java , 。