Androidマルチスレッド--スレッドロックの概要

17867 ワード

                ,        ,                  ,            。

一、synchronize同期ロック(内蔵ロック)マルチスレッドが同じ位置を同時に操作することを防止するために、オブジェクトとclassをロックすることができる.
public class synchronizedDemo{
//    
public synchronized void method{
//doSomething
}
//   
synchronizedthis){
//doSomething
}
//  class  
synchronized(synchronizedDemo.class){
//doSomething
}
//      
public synchronized  static void method{
//doSomething
}
}

同期メソッドと同期ブロックロックはオブジェクトであり、同期classと同期静的メソッドロックはclassオブジェクトである.ロックclassオブジェクトがマルチスレッドで同じsynchronizedコードブロックにアクセスする場合、ロックオブジェクトがマルチスレッドで同じオブジェクトにアクセスするsynchronizedコードブロックである場合
二、ReentrantLock(表示ロック)java 6.0後に増加する新しいメカニズムはsynchronizeとは異なり、synchronizedの取得と解放は同じコードブロックにあり、ロックの取得と解放を自由に制御することができます.同時に、輪訓所、タイミングロック、公平ロック、非公平ロックを提供することができる.lock()—>ロックの取得;tryLock()->ロックの取得を試みます.tryLock(long timeout,timeUnit Unit)->取得タイムアウトの時間を指定unLock()->ロック解除newCondition()->ロックを取得するcondition ps:ロックを表示した後にロックを解除する必要があります.そうしないと、デッドロックになります.これもsynchronizedの代わりにロックが完了していない理由です.
reentrantlockにはもう一つの非常に重要な方法があります.newCondition()は、wait()、notify()、notifyall()などの方法を完了するためにロックに作用する条件です.
次はreentrantLockで完了した境界のあるブロックキューです
public class MyArrayBlockingQueue {
    private final T[] items;
    //   
    private final Lock lock = new ReentrantLock();
    //     
    private Condition notFull = lock.newCondition();
    //     
    private Condition notEmpty = lock.newCondition();
    //  
    private int head;
    //  
    private int tail;
    //      
    private int count;

    public MyArrayBlockingQueue(int MaxSize) {
        items = (T[]) new Object[MaxSize];
    }

    public MyArrayBlockingQueue() {
        this(10);
    }

    public void put(T t) {
        lock.lock();
        try {
            while (count == getCapacity()) {
                System.out.println("    ,   ");
                notFull.wait();
            }
            items[tail] = t;
            if (++tail == getCapacity())
                tail = 0;
            ++count;
            notEmpty.signalAll();//         
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public T take() {
        lock.lock();
        try {
            while (count == getCapacity()) {
                System.out.println("    ,   ");
                notEmpty.wait();
            }
            T ret = items[head];
            items[head] = null;
            if (++head == getCapacity())
                head = 0;
            --count;
            notFull.signalAll();//         
            return ret;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        return null;
    }

    public int getCapacity() {
        return items.length;
    }

    public int size() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

三、信号量Semaphoreの本質は「共有ロック」であり、スレッドは実行を継続するために信号量(acquire)を取得しなければならない.そうしないと待機する.実行が完了した後、信号(release)を解放し、他のスレッドは信号を取得しなければならない.サンプルコード
public static void main(String[] args) {
                //    
ExecutorService exec = Executors.newCachedThreadPool();
                //   3       
                final Semaphore semp = new Semaphore(3);
                 //   5      
                 for (int index = 0; index < 5; index++) {
                              final int NO = index;
                              Runnable run = new Runnable() { 
                                  public void run() {
                                  try {
                                                                    //     
                                                                                            semp.acquire();
                                                                    System.out.println("Accessing: " + NO);
                                                                    Thread.sleep((long) (Math.random() * 10000));
                                                                    //     ,  
                                                                    semp.release();
                                                                    System.out.println("-----------------"+semp.availablePermits());
                                                            } catch (InterruptedException e) {
                                                                    e.printStackTrace();
                                                            }
                                                  }
                                      };
                      exec.execute(run);
             }
             //      
             exec.shutdown();
       }
} 

実行結果は、Accessing:0 Accessing:1 Accessing:2—————0 Accessing:4—————1 Accessing:3
四、循環柵CyclicBarrier CyclicBarrierは同期補助クラスであり、N個のスレッドが共通点に達するまで互いに待つことを許可し、さらに一緒に実行を継続する.再利用可能なのでループBarrierと呼ぶ.例:競走の時、全員が準備ができたら、スタートする.
public class CyclicBarrierTest {  
  2.   
  3.     public static void main(String[] args) throws IOException, InterruptedException {  
  4.         //       4,        3   ,         
  5.         //Waits until all parties have invoked await on this barrier.   
  6.         CyclicBarrier barrier = new CyclicBarrier(3);  
  7.   
  8.         ExecutorService executor = Executors.newFixedThreadPool(3);  
  9.         executor.submit(new Thread(new Runner(barrier, "1   ")));  
  10.         executor.submit(new Thread(new Runner(barrier, "2   ")));  
  11.         executor.submit(new Thread(new Runner(barrier, "3   ")));  
  12.   
  13.         executor.shutdown();  
  14.     }  
  15. }  
  16.   
  17. class Runner implements Runnable {  
  18.     //        ,           ,            (common barrier point)  
  19.     private CyclicBarrier barrier;  
  20.   
  21.     private String name;  
  22.   
  23.     public Runner(CyclicBarrier barrier, String name) {  
  24.         super();  
  25.         this.barrier = barrier;  
  26.         this.name = name;  
  27.     }  
  28.   
  29.     @Override  
  30.     public void run() {  
  31.         try {  
  32.             Thread.sleep(1000 * (new Random()).nextInt(8));  
  33.             System.out.println(name + "     ...");  
  34.             // barrier await  ,            barrier     await     ,     。  
  35.             barrier.await();  
  36.         } catch (InterruptedException e) {  
  37.             e.printStackTrace();  
  38.         } catch (BrokenBarrierException e) {  
  39.             e.printStackTrace();  
  40.         }  
  41.         System.out.println(name + "   !");  
  42.     }  
  43. }  

出力結果:3番の選手が準備できました...2番の選手が準備できました...1番の選手が準備できました...1番の選手がスタートします!2番選手スタート!3番選手スタート!
五、閉鎖CountDownLatch CountDownLatchも同期補助クラスである.彼の役割は、すべてのスレッドがイベントを完了し、呼び出し(countDown)が完了するまで、1つ以上のスレッドを待つことです.サンプルコード:
  1. public class countDownlatchTest {  
  2.     public static void main(String[] args) throws InterruptedException {  
  3.         CountDownLatch countDownLatch = new CountDownLatch(5);  
  4.         for(int i=0;i<5;i++){  
  5.             new Thread(new readNum(i,countDownLatch)).start();  
  6.         }  
  7.         countDownLatch.await();  
  8.         System.out.println("    ,    ");
  9.        //dosomething  
  10.     }  
  11.   
  12.     static class readNum  implements Runnable{  
  13.         private int id;  
  14.         private CountDownLatch latch;  
  15.         public readNum(int id,CountDownLatch latch){  
  16.             this.id = id;  
  17.             this.latch = latch;  
  18.         }  
  19.         @Override  
  20.         public void run() {  
  21.             synchronized (this){  
  22.                 System.out.println("id:"+id);  
  23.                 latch.countDown();  
  24.                 System.out.println("     "+id+"  ,      ");  
  25.             }  
  26.         }  
  27.     }  
  28. }  

出力結果:id:1スレッドグループタスク1終了、他タスク継続id:0スレッドグループタスク0終了、他タスク継続id:2スレッドグループタスク2終了、他タスク継続id:3スレッドグループタスク3終了、他タスク継続id:4スレッドグループタスク4終了、他タスク継続等終了、継続実行
cyclicbarrier countdownlatch区別:(個人見解)1、明らかな違い:cyclicbarrierは再利用可能で、後者はだめです.2、前者はすべてのプレイヤー(スレッド)が揃うのを待ってから、一緒に後続のイベントをし、後者はすべてのプレイヤー(スレッド)が何らかの条件を達成するのを待ってから、後続のイベントを続けることに偏っている.