Java 使用布尔值进行同步
以下代码在并发访问列表时是线程安全的吗?Java 使用布尔值进行同步,java,concurrency,java.util.concurrent,Java,Concurrency,Java.util.concurrent,以下代码在并发访问列表时是线程安全的吗? volatile限定是否在此处添加任何值 class concurrentList{ private AtomicBoolean locked = new AtomicBoolean(true); volatile List<Integer> list=new LinkedList<Integer>(); long start = System.currentTimeMill
volatile限定是否在此处添加任何值
class concurrentList{
private AtomicBoolean locked = new AtomicBoolean(true);
volatile List<Integer> list=new LinkedList<Integer>();
long start = System.currentTimeMillis();
long end = start + 60*100;
public void push(int e){
while(!locked.get());
list.add(e);
while(!locked.compareAndSet(true,false));
}
public int pop(){
int elem;
while(locked.get());
elem=(Integer)list.remove(0);
while(!locked.compareAndSet(false,true));
return elem;
}
....
}
类并发列表{
private AtomicBoolean locked=新的AtomicBoolean(true);
volatile List List=new LinkedList();
长启动=System.currentTimeMillis();
长端=起点+60*100;
公共无效推送(INTE){
而(!locked.get());
列表.添加(e);
而(!locked.compareAndSet(true,false));
}
公共int-pop(){
内因;
while(locked.get());
elem=(整数)列表。删除(0);
而(!locked.compareAndSet(false,true));
返回元素;
}
....
}
不,它不是线程安全的。调用push()
的两个线程完全可以将锁定的值读取为true,然后并发地添加到链接列表中。由于LinkedList不是线程安全的,因此您的代码不是线程安全的
要锁定,请使用一个锁,而不是原子布尔。在这种特殊情况下,我将使用synchronized作为方法,而不是volatile作为变量,根据
[this question][1]
类并发列表{
private AtomicBoolean locked = new AtomicBoolean(true);
List<Integer> list=new LinkedList<Integer>();
long start = System.currentTimeMillis();
long end = start + 60*100;
public synchronized void push(int e){
while(someLock.notCondition()); //only an example
list.add(e);
someLock.notify();
}
public synchronized int pop(){
int elem;
while(someLock.notCondition());
elem=(Integer)list.remove(0);
someLock.notify()
return elem;
}
....
}
private AtomicBoolean locked=新的AtomicBoolean(true);
列表=新建LinkedList();
长启动=System.currentTimeMillis();
长端=起点+60*100;
公共同步无效推送(int e){
while(someLock.notCondition());//仅举一个例子
列表.添加(e);
someLock.notify();
}
公共同步int-pop(){
内因;
while(someLock.notCondition());
elem=(整数)列表。删除(0);
someLock.notify()
返回元素;
}
....
}
对于这种情况,我建议使用。这把锁有两个用途。当readLock打开时,在释放写锁之前,不允许读取。读锁是非阻塞的:
class concurrentList{
ReadWriteLock lock =new ReentrantReadWriteLock();
private AtomicBoolean locked = new AtomicBoolean(true);
volatile List<Integer> list=new LinkedList<Integer>();
long start = System.currentTimeMillis();
long end = start + 60*100;
public void push(int e){
lock.writeLock().lock();
try{
list.add(e);
} finally {
lock.writeLock().unlock();
}
}
public int pop(){
lock.readLock().lock();
try {
int elem;
elem=(Integer)list.remove(0);
} finally {
lock.readLock().unlock();
}
return elem;
}
类并发列表{
ReadWriteLock lock=new ReentrantReadWriteLock();
private AtomicBoolean locked=新的AtomicBoolean(true);
volatile List List=new LinkedList();
长启动=System.currentTimeMillis();
长端=起点+60*100;
公共无效推送(INTE){
lock.writeLock().lock();
试一试{
列表.添加(e);
}最后{
lock.writeLock().unlock();
}
}
公共int-pop(){
lock.readLock().lock();
试一试{
内因;
elem=(整数)列表。删除(0);
}最后{
lock.readLock().unlock();
}
返回元素;
}
。。。。
对于任何并发编程的三个概念,在编写一个线程安全编程时需要考虑更多。当一个并发程序没有被正确写入时,错误倾向于分为三类:<强> AOMITION<强>,<强>能见度< /强>,或排序 原子性:处理哪些动作和动作集具有不可分割的效果。它通常被认为是互斥的 可见性:确定一个线程的效果何时可以被另一个线程看到 排序:确定何时可以看到一个线程中的操作相对于另一个线程发生无序 在您的代码第一期中,它未能满足上述所有概念。您没有使用锁,因此无法确保可见性和顺序。
对于线程安全,您可以在并发API中使用
ReadWriteLock
。或者有可用的非阻塞链表,将使用compareAndset 不确定为什么在push
和pop
方法中有不同的锁定条件。但是显然,为什么不使用一个对象呢?确切地说,再加上一个对象来具体快速地回答什么是someLock
?