关闭

Lock and Condition 实现线程同步

109人阅读 评论(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网站的观点或立场
    个人资料
    • 访问:33817次
    • 积分:818
    • 等级:
    • 排名:千里之外
    • 原创:46篇
    • 转载:25篇
    • 译文:1篇
    • 评论:4条
    最新评论