多线程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 = 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 = 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();
          }
      }

    }
}

多线程09-Lock和Condition

时间: 2024-10-10 15:21:46

多线程09-Lock和Condition的相关文章

Java并发(三)使用显式的Lock和Condition对象

在之前的Java并发(一)wait()与notifyAll()一文中的例子中,我们使用了wait()和notifyAll()来模拟了给汽车打蜡和抛光的情景.在JavaSE5中,还提供了java.util.concurrent.locks.Condition对象供我们使用.你可以在Condition上调用await()来挂起一个任务.当外部条件发生变化,意味着某个任务应该继续执行时,你可以通过调用signal()来通知这个任务,或者调用signalAll()来唤醒所有在这个Condition上被其

黑马程序员–Java之多线程09

黑马程序员–Java之多线程09 一.线程和进程 在Java中,并发机制非常重要,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程.多线程就是指一个应用程序中有多条并发执行的线索,每条线索都被称作一个线程,它们会交替执行,彼此间可以进行通信.多线程是非常复杂的机制,在每个操作系统中的运行方式也存在差异,window操作系统是多任务操作系统,它以进程为单位.一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程,也就是正在执行的程序.系统

JAVA 并发编程-线程同步通信技术(Lock和Condition)(十)

在之前的博客中已经介绍过线程同步通信技术<JAVA 并发编程-传统线程同步通信技术(四)>,上篇是使用的synchronized,wait,notify来实现,今天我们使用的是Lock和Condition,下面我们结合两者对比来学习. 简单的Lock锁应用: /** * 简单Lock的应用 * @author hejingyuan * */ public class LockTest { public static void main(String[] args) { new LockTest

【Java并发工具类】Lock和Condition

前言 Java SDK并发包通过Lock和Condition两个接口来实现管程,其中Lock用于解决互斥问题,Condition用于解决同步问题.我们需要知道,Java语言本身使用synchronized实现了管程的,那么为什么还在SDK中提供另外一种实现呢?欲知为何请看下文. 下面将先阐述再造管程的理由,然后详细介绍Lock和Condition,最后再看实现同步机制时是选择synchronized还是SDK中的管程. 再造管程的理由 Java本就从语言层面实现了管程,然而后面又在SDK中再次现

使用JUC并发工具包的Lock和Condition,实现生产者和消费者问题中的有界缓存

JDK5.0之前,用java实现生产者和消费者的唯一方式就是使用synchronized内置锁和wait/notify条件通知机制.JDK5.0之后提供了显示锁Lock和条件队列Condition,与内置锁和内置条件队列相对应,但是显示的锁和条件队列,功能更强大,更灵活.此外JDK5.0之后还提供了大量很有用的并发工具类,如BlockingQueue等,基于这些数据结构,能够方便.快速.高效的构建自己应用需要的效果.这里我们简单使用下显示锁和条件队列,来模拟有界缓存的实现,功能类似于JDK内置的

【Java线程】锁机制:synchronized、Lock、Condition

http://www.infoq.com/cn/articles/java-memory-model-5  深入理解Java内存模型(五)——锁 http://www.ibm.com/developerworks/cn/java/j-jtp10264/  Java 理论与实践: JDK 5.0 中更灵活.更具可伸缩性的锁定机制 http://blog.csdn.net/ghsau/article/details/7481142 1.synchronized 把代码块声明为 synchronize

c#多线程中Lock()关键字的用法小结

本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待. 每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生.

使用lock和condition实现的阻塞队列-字符串

在jdk 的API中提供了一个字符串的阻塞队列 : class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count;

java线程通讯——使用Lock和Condition代替synchronized 和 wait, notify notifyAll()

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作. 此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象. 使用生产者和消费者为例!!! import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 使

C++11中的mutex, lock,condition variable实现分析

本文分析的是llvm libc++的实现:http://libcxx.llvm.org/ C++11中的各种mutex, lock对象,实际上都是对posix的mutex,condition的封装.不过里面也有很多细节值得学习. std::mutex 先来看下std::mutex: 包增了一个pthread_mutex_t __m_,很简单,每个函数该干嘛就干嘛. class mutex { pthread_mutex_t __m_; public: mutex() _NOEXCEPT {__m