2017-06-03 71 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。