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