需求: 多个生产者不断的生产产品,多个消费者不断的消费产品,仓库可以存放10个产品。 第一批产品需要生产20个产品,并消费完毕。
这次不使用独占锁,使用CPU原语CAS.
CAS 简单来说就是由CPU比较内存位置的值是否为当前值,如是则将其设置为next,如否则返回false.因此上面的代码片段要在一个无限循环中执行,这样可以保证并发时id的顺序.
基于CAS操作可以认为是无阻塞的,并且由于CAS操作是CPU原语,因此其性能会好于之前同步锁得方式。
这里使用CAS原语. 当多个线程同时执行时,只有一个会成功.
这次不使用独占锁,使用CPU原语CAS.
CAS 简单来说就是由CPU比较内存位置的值是否为当前值,如是则将其设置为next,如否则返回false.因此上面的代码片段要在一个无限循环中执行,这样可以保证并发时id的顺序.
基于CAS操作可以认为是无阻塞的,并且由于CAS操作是CPU原语,因此其性能会好于之前同步锁得方式。
package ycl.learn.effective.java.thread.pc;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 公共资源类
*/
public class PublicResourceAtomic {
private BlockingQueue<Product> queue = new LinkedBlockingQueue<Product>(10);
public static final int MAX_RESOURCE = 20;
private AtomicInteger lock = new AtomicInteger(0);
private AtomicInteger index = new AtomicInteger(0);
/**
* 增加公共资源
*/
public boolean increace() {
while(true){
int s = lock.get();
int nextSeed = s+1;
if(lock.compareAndSet(s, nextSeed)){//CAS 原语实现
if(isComplete()){//生产任务完成
return false;
}
int tindex = index.incrementAndGet();
Product p = new Product(tindex);
try {
queue.put(p);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"increace:" + tindex);
return true;
}
}
}
/**
* 减少公共资源
*/
public boolean decreace() {
while(true){
int s = lock.get();
int nextSeed = s;
if(lock.compareAndSet(s, nextSeed)){//CAS 原语实现
if (isEmpty()) {
if(isComplete()){//如果消费结束,将会死锁,因为isEmpty()is true forever, 所以不管你如何notify,他始终等待,添加当wait被notify时,消费任务完成,退出。
return false;
}
}
if(!isEmpty()){
Product p = null;
try {
p = queue.take();
} catch (InterruptedException e) {
System.err.println(e);
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"decreace:" + p.index);
}
return true;
}
}
}
public boolean isFull(){
return queue.size() == 10;
}
/**
* 判断是否空了
*/
public boolean isEmpty() {
return queue.isEmpty();
}
/**
* 判断生产完毕
*/
public boolean isComplete() {
return index.get() >= MAX_RESOURCE;
}
class Product{
public int index;
public Product(int index){
this.index = index;
}
}
}
这里使用CAS原语. 当多个线程同时执行时,只有一个会成功.