2017-06-03 72 views
3

在并发访问List时,以下代码是线程安全的吗?
挥发性限定在这里添加任何值吗?使用布尔值进行同步

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; 
     } 
.... 
} 
+0

不确定为什么'push'和'pop'方法有不同的锁定条件。但是从这一点开始,为什么不使用['java.util.concurrent.Lock'](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html ?is-external = true)对象? – n247s

回答

2

不,它不是线程安全的。两个调用push()的线程可以完全同时读取锁定为真,然后同时添加到链接列表。由于LinkedList不是线程安全的,因此您的代码不是线程安全的。

要锁定,请使用锁而不是AtomicBoolean。

+0

确切地说,加上一个具体的和快速回答 –

0

在这种格外情况下,我使用同步的方法,以及根据[this question][1]

类concurrentList {

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; 
    } 
.... 
} 
+0

什么是'someLock'? – saka1029

1

酒店这样的情况下,我建议使用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; 
    } 

.... }

0

增加更多的已经回答即加入对于任何并发编程三个概念时,需要在编写线程安全编程时考虑。当并发程序写入不正确时,错误倾向于分为三类:Aomicity,可见性订购

原子性:处理哪些动作和动作集具有不可分割的效果。它通常被认为是互斥。

可见性:确定一个线程的效果何时可以被另一个线程看到。

订购:确定在一个线程中的动作可以看出相对于其他

在你的代码,第一个问题就失败以上所有concepts.You提到不按顺序发生在不使用锁,因此可见性和订购将不会得到保证。 对于线程安全,您可以在并发API中使用ReadWriteLock。或者有可用的非阻塞链接列表,它将使用compareAndset。