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 用户交换数据,两者到达同一个时间地点后 拿着数据,这个时候就开始交换数据