使用布尔值同步
Using boolean to synchronize
以下代码在并发访问 List 时是否线程安全?
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;
}
....
}
不,它不是线程安全的。调用 push()
的两个线程可以完美地同时读取锁定为真,然后并发添加到链表中。由于 LinkedList 不是线程安全的,因此您的代码也不是线程安全的。
要锁定,请使用锁,而不是 AtomicBoolean。
在这种特殊情况下,根据 [this question][1]
,我将对方法使用 synchronized,而不是对变量使用 volatile
class 并发列表{
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;
}
....
}
客栈这种情况我会推荐使用ReadWriteLock。这把锁有两个用途。当 readLock 打开时,不允许读取,直到写入锁定 released.Read 锁定是非阻塞的:
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;
}
.....
}
在答案中添加更多即对于任何并发编程三个概念,您在编写线程安全编程时需要考虑。当并发程序编写不正确时,错误往往属于三个之一类别:Aomicity、Visibility 或 Ordering。
原子性 :处理哪些动作和动作集不可分割effects.It通常被认为是互斥的。
Visibility :确定一个线程的效果何时可以被另一个线程看到。
排序 :确定何时可以看到一个线程中的操作相对于另一个线程发生乱序
在您的代码中,第一个问题是上面提到的所有问题都失败了 concepts.You 没有使用锁,因此无法确保可见性和顺序。
对于线程安全,您可以在并发 API.Or 中使用 ReadWriteLock
有可用的非阻塞链表,它将使用 compareAndset。
以下代码在并发访问 List 时是否线程安全?
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;
}
....
}
不,它不是线程安全的。调用 push()
的两个线程可以完美地同时读取锁定为真,然后并发添加到链表中。由于 LinkedList 不是线程安全的,因此您的代码也不是线程安全的。
要锁定,请使用锁,而不是 AtomicBoolean。
在这种特殊情况下,根据 [this question][1]
class 并发列表{
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;
}
....
}
客栈这种情况我会推荐使用ReadWriteLock。这把锁有两个用途。当 readLock 打开时,不允许读取,直到写入锁定 released.Read 锁定是非阻塞的:
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;
}
..... }
在答案中添加更多即对于任何并发编程三个概念,您在编写线程安全编程时需要考虑。当并发程序编写不正确时,错误往往属于三个之一类别:Aomicity、Visibility 或 Ordering。
原子性 :处理哪些动作和动作集不可分割effects.It通常被认为是互斥的。
Visibility :确定一个线程的效果何时可以被另一个线程看到。
排序 :确定何时可以看到一个线程中的操作相对于另一个线程发生乱序
在您的代码中,第一个问题是上面提到的所有问题都失败了 concepts.You 没有使用锁,因此无法确保可见性和顺序。
对于线程安全,您可以在并发 API.Or 中使用 ReadWriteLock
有可用的非阻塞链表,它将使用 compareAndset。