首页 > 代码库 > 多线程09-Lock和Condition

多线程09-Lock和Condition

1.概念

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象。

 

2.案例

package org.lkl.thread;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class LockFoo {    /**     * 两个线程打印姓名     */            public static void main(String[] args) {        final Outputter out = new Outputter() ;        new Thread(new Runnable() {                        @Override            public void run() {                 while(true){                     try {                        Thread.sleep(200) ;                        out.print("zhangsan") ;                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                 }            }        }).start();                        new Thread(new Runnable() {                                        @Override                    public void run() {                         while(true){                             try {                                Thread.sleep(1000) ;                                out.print("liaokailinliaokailinliaokailinliaokailinliaokailinliaokailin") ;                            } catch (InterruptedException e) {                                e.printStackTrace();                            }                         }                    }                }).start();    }            }class Outputter{    Lock lock = new ReentrantLock() ;    public void print(String name){        lock.lock() ; //加上锁  只有等到操作全完成以后才释放锁        try {            if(name!=null){                for(int i = 0 ; i<name.length() ;i++){                    System.out.print(name.charAt(i));                }                System.out.println();            }        }finally {            lock.unlock() ;//解锁 一般都在finally中解锁  不过程序是否有异常 最终都要解锁 否则会导致阻塞        }    }}

 

    

3. 读写锁

     读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;

如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!

package cn.itcast.heima2;import java.util.Random;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockTest {    public static void main(String[] args) {        final Queue3 q3 = new Queue3();        for(int i=0;i<3;i++)        {            new Thread(){                public void run(){                    while(true){                        q3.get();                                            }                }                            }.start();            new Thread(){                public void run(){                    while(true){                        q3.put(new Random().nextInt(10000));                    }                }                                        }.start();        }            }}class Queue3{    private Object data = http://www.mamicode.com/null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。    ReadWriteLock rwl = new ReentrantReadWriteLock();    public void get(){        rwl.readLock().lock();        try {            System.out.println(Thread.currentThread().getName() + " be ready to read data!");            Thread.sleep((long)(Math.random()*1000));            System.out.println(Thread.currentThread().getName() + "have read data :" + data);                    } catch (InterruptedException e) {            e.printStackTrace();        }finally{            rwl.readLock().unlock();        }    }        public void put(Object data){        rwl.writeLock().lock();        try {            System.out.println(Thread.currentThread().getName() + " be ready to write data!");                                Thread.sleep((long)(Math.random()*1000));            this.data =http://www.mamicode.com/ data;                    System.out.println(Thread.currentThread().getName() + " have write data: " + data);                            } catch (InterruptedException e) {            e.printStackTrace();        }finally{            rwl.writeLock().unlock();        }                }}

 

4. Condition

 

package org.lkl.thead.foo01;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ConditionFoo {    /**     * 子线程先执行10次 然后主线程再执行20次 如此循环50次     */    public static void main(String[] args) {    final Business b = new Business() ;        //子线程执行50次        for(int i = 1 ;i<=50 ;i++){            final int seq = i ;            new Thread(new Runnable() {                                public void run() {                    b.sub(seq) ;                }            }).start() ;        }                //主线程执行50次        for(int i = 1 ;i<=50 ;i++){               b.main(i) ;                 }            }        }class Business{    boolean isSub =  true ;        Lock lock = new ReentrantLock() ;    Condition condition = lock.newCondition() ;    //子线程执行10次    public  void sub(int j ){  //加lock以后不需要synchronized        lock.lock() ;        try {            while(!isSub){                try {                    condition.await() ;                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            for(int i = 1 ;i<=10 ;i++){                System.out.println("sub thread execute times " + i  + " loop of "+ j);            }                        isSub = false ;            condition.signalAll() ;        } finally {            lock.unlock() ;        }            }            //主线程执行20次    public  void main(int j ){        lock.lock() ;        try {            while(isSub){                try {                    condition.await() ;                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            for(int i = 1 ;i<=20 ;i++){                System.out.println("main thread execute times " + i  + " loop of "+ j);            }                        isSub = true ;        //    condition.signal() ;            condition.signalAll() ;        }finally {            lock.unlock() ;        }    }}

 

 

 5. 通过condition实现三个线程之间的通信

package cn.itcast.heima2;import java.util.concurrent.atomic.AtomicInteger;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ThreeConditionCommunication {    /**     * @param args     */    public static void main(String[] args) {                final Business business = new Business();        new Thread(                new Runnable() {                                        @Override                    public void run() {                                            for(int i=1;i<=50;i++){                            business.sub2(i);                        }                                            }                }        ).start();                new Thread(                new Runnable() {                                        @Override                    public void run() {                                            for(int i=1;i<=50;i++){                            business.sub3(i);                        }                                            }                }        ).start();                        for(int i=1;i<=50;i++){            business.main(i);        }            }    static class Business {            Lock lock = new ReentrantLock();            Condition condition1 = lock.newCondition();            Condition condition2 = lock.newCondition();            Condition condition3 = lock.newCondition();          private int shouldSub = 1;          public  void sub2(int i){              lock.lock();              try{                  while(shouldSub != 2){                      try {                        condition2.await();                    } catch (Exception e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                  }                    for(int j=1;j<=10;j++){                        System.out.println("sub2 thread sequence of " + j + ",loop of " + i);                    }                  shouldSub = 3;                  condition3.signal();              }finally{                  lock.unlock();              }          }          public  void sub3(int i){              lock.lock();              try{                  while(shouldSub != 3){                      try {                        condition3.await();                    } catch (Exception e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                  }                    for(int j=1;j<=20;j++){                        System.out.println("sub3 thread sequence of " + j + ",loop of " + i);                    }                  shouldSub = 1;                  condition1.signal();              }finally{                  lock.unlock();              }          }                              public  void main(int i){              lock.lock();              try{                 while(shouldSub != 1){                          try {                            condition1.await();                        } catch (Exception e) {                            // TODO Auto-generated catch block                            e.printStackTrace();                        }                      }                    for(int j=1;j<=100;j++){                        System.out.println("main thread sequence of " + j + ",loop of " + i);                    }                    shouldSub = 2;                    condition2.signal();          }finally{              lock.unlock();          }      }        }}