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 , 。