关闭

Lock and Condition 实现线程同步

148人阅读 评论(0) 收藏 举报
分类:

lock 和 synchronized 相似  可以替代这个关键字

Lock lock=new ReentrantLock()

lock.lock(); 进入共享代码区

try{

code......

}finnaly{

lock.unlock()

}

lock.unlock()解开锁

基本和synchronize是一样的,原来的synchronized是锁对象,这个lock相当于有了单独的对象

为了避免贡献代码部分发生异常导致 无法释放锁,所以加了一个try catch finnaly来保证每次锁都能够释放


注意,synchronized是用来控制实现原子性的,必须等这部分代码执行完,其他线程才能使用这部分代码


读写锁分为读锁和写锁,读锁和读锁不互斥,读锁和写锁互斥,写锁和写锁互斥 


有点模糊 解释一下,这个类 里面有一个共享数据data,同时有一个度方法和一个写方法,在读方法前面加上读锁,在写方法前面加上写锁,这样就可以看到多个线程同时读 但是只有一个线程在执行写方法,我们在这里不能用lock的原因是,lock一旦锁上之后,没有办法进行多个线程的读操作,这样读操作也变为互斥操作了,所以我们使用读写锁来控制这种读写操作。

 condition 主要用于线程通信,功能和wait notify一样,condition.await  condition.signal  可以实现多路等待

阻塞队列,主要是用来实现一个队列,在空的时候可以阻塞取数据,在满的时候后可以阻塞放数据


private final Condition notFull;
private final Condition notEmpty;

public ArrayBlockingQueue(int capacity, boolean fair) {
        //省略其他代码
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }

public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            insert(e);
        } finally {
            lock.unlock();
        }
}

public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return extract();
  } finally {
            lock.unlock();
        }
}

private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();
    }


信号灯技术 semaphore



Semaphore维护了当前访问的个数,提供同步机制,控制同时访问的个数。在数据结构中链表可以保存“无限”的节点,用Semaphore可以实现有限大小的链表。另外重入锁 ReentrantLock 也可以实现该功能,但实现上要复杂些。 

下面的Demo中申明了一个只有5个许可的Semaphore,而有20个线程要访问这个资源,通过acquire()和release()获取和释放访问许可。

package com.test;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Semaphore;

public class TestSemaphore {

                public static void main(String[] args) {

                // 线程池

                ExecutorService exec = Executors.newCachedThreadPool();

                // 只能5个线程同时访问

                final Semaphore semp = new Semaphore(5);

                 // 模拟20个客户端访问

                 for (int index = 0; index < 20; 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: 3

Accessing: 4

Accessing: 2

-----------------0

Accessing: 6

-----------------1

Accessing: 7

-----------------1

Accessing: 8

-----------------1

Accessing: 10

-----------------1

Accessing: 9

-----------------1

Accessing: 5

-----------------1

Accessing: 12

-----------------1

Accessing: 11

-----------------1

Accessing: 13

-----------------1

Accessing: 14

-----------------1

Accessing: 15

-----------------1

Accessing: 16

-----------------1

Accessing: 17

-----------------1

Accessing: 18

-----------------1

Accessing: 19

CyclicBarrier 主要是用来控制线程都同时到达之后再往后走 类似与一个约定 所有的线程都到达路障地点之后才开始往下走



cuuntdownlaunch  是一个计数器,通过调用countDown 做减一操作,通过wait 等待这个计数器减为0


exchange 用户交换数据,两者到达同一个时间地点后 拿着数据,这个时候就开始交换数据




0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

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

在之前的博客中已经介绍过线程同步通信技术《JAVA 并发编程-传统线程同步通信技术(四)》,上篇是使用的synchronized,wait,notify来实现,今天我们使用的是Lock和Condition,下面我们结合两者对比来学习。 简单的Lock锁应用:/** * 简单Lock的应用...
  • hejingyuan6
  • hejingyuan6
  • 2015-08-01 10:01
  • 2156

黑马程序员——Java5中的线程并发库(一)---概述、线程池、Callable和Future、Lock和Condition

多线程与数据共享 一.ThreadLocal实现线程范围的共享变量 1.见下面的示意图和辅助代码解释ThreadLocal的作用和目的,用于实现线程内数据共享,即对于相同的程序代码,多个模块在同一个线程中运行时要共享一份数据,而在另外线程中运行时共享另外一份数据。 注1:线程范围内共享数据的示...
  • ruying_suixing
  • ruying_suixing
  • 2014-10-17 16:05
  • 657

java并发锁ReentrantLock源码分析二之Condition实现原理

本文深入分析了并发锁ReentrantLock Condtion的实现原理,一个很重要的关键是await先释放锁,然后阻塞,在条件队列中等待被唤醒,每个CondtionObject维护着一个条件队列,一个ReentrantLock维护一个同步队列。await被唤醒后,会进入同步队列,等待获取锁,aw...
  • prestigeding
  • prestigeding
  • 2016-11-14 13:55
  • 1834

java并发包学习系列:重入锁与Condition条件

重入锁   这里介绍一下synchronized、wait、notify方法的替代品(或者说是增强版)-重入锁。重入锁是可以完全替代以上的内容的。并且重入锁的性能是远高于synchronized的,但是jdk6.0开始,jdk对synchronized做了大量的优化,使得两者性能差距不大。   ...
  • a910626
  • a910626
  • 2016-07-13 19:43
  • 1398

Java并行编程-lock中使用多条件condition(生产者消费者模式实例)

Java 并发包下的提供Lock,Lock相对于Synchronized可以更好的解决线程同步问题,更加的灵活和高效,并且ReadWriteLock锁还能实现读、写的分离。但线程间仅仅互斥是不够的,还需要通信,本篇的内容是基于上篇之上,使用Lock如何处理线程通信。阻塞队列(BlockingQueu...
  • chenchaofuck1
  • chenchaofuck1
  • 2016-06-05 23:37
  • 6964

多线程中使用Lock和Condition机制

1、资源类 package cn.toltech.t_concurrent; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Condition; import java.u...
  • xiaoyezi1001
  • xiaoyezi1001
  • 2015-01-22 08:54
  • 377

Java5 多线程(三)--Lock和Condition实现线程同步通信

1>Lock:          Lock比传统线程模型中的Synchronied方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码段要实现同步互斥的效果,它们必须用同一个Lock对...
  • johnny901114
  • johnny901114
  • 2013-03-20 11:54
  • 11799

ReentrantLock(二):正确使用Condition实现等待与通知

关键字synchronized与wait()和notify()/notifyAll()方法相结合可以实现等待/通知模式。 类ReentrantLock同样可以实现该功能,但是要借助于Condition对象。它具有更好的灵活性,比如可以实现多路通知功能,也就是在一个Lock对象里面可以创建多个Con...
  • zhang199416
  • zhang199416
  • 2017-04-26 09:30
  • 473

Java ReentranLock同步锁和Condition条件的使用

java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为 Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。 ReentrantLock 类实现了 Lock ,...
  • y874961524
  • y874961524
  • 2017-01-25 00:40
  • 779

关于Java同步锁中await和signalAll的使用经验

当使用Lock来保证线程同步时,需使用Condition对象来使线程保持协调。Condition实例被绑定在一个Lock的对象上,使用Lock对象的方法newCondition()获取Condition的实例。Condition提供了下面三种方法,来协调不同线程的同步: 1、await():导致当前...
  • zqzxken
  • zqzxken
  • 2015-06-04 17:22
  • 3504
    个人资料
    • 访问:44638次
    • 积分:931
    • 等级:
    • 排名:千里之外
    • 原创:46篇
    • 转载:25篇
    • 译文:1篇
    • 评论:4条
    文章分类
    最新评论