condition.await()并发问题

问题描述

condition.await()并发问题

public class BlockArrayList extends ArrayList
{
/**

* long serialVersionUID:TODO(用一句话描述这个变量表示什么)

*

* @since 1.0.0

*/

private static final long serialVersionUID = 1L;

private ReentrantLock lock = new ReentrantLock();

private Condition notEmpty = lock.newCondition();

public int i = 0;

public Exception ee;

public E take() throws InterruptedException
{
    try
    {
        lock.lock();
        E e = null;
        int size = this.size();
        if(size == 0)
        {
            notEmpty.await();
        }
        i++;
        System.out.println(i);
        try
        {
            e = this.remove(0);
        }
        catch(Exception e1)
        {
            ee = e1;
        }

        return e;
    }
    finally
    {
        lock.unlock();
    }
}

public boolean offer(E e)
{
    try
    {
        lock.lock();
        this.add(e);
        notEmpty.signal();
        return true;
    }
    finally
    {
        lock.unlock();
    }
}

public void op()
{
    E s = null;
    try
    {
        s = this.take();
    }
    catch (InterruptedException e)
    {
        System.out.println(Thread.currentThread().getName() +" 被动结束");
        e.printStackTrace();
    }
}

public class MyThreadFactory implements ThreadFactory
{

    private AtomicInteger NUMBER = new AtomicInteger(0);

    @Override
    public Thread newThread(Runnable r)
    {
        Thread t = new Thread(r);
        t.setName("shaoweiThread-"+NUMBER.decrementAndGet());
        return t;
    }
}

public static void main(String[] args)
{
    final BlockArrayList<String> list = new BlockArrayList<String>();
    ThreadFactory threadThread = list.new MyThreadFactory();

    Thread t = threadThread.newThread(new Runnable()
    {
        @Override
        public void run()
        {
            int i = 0;
            while(i <410000)
            {
                list.op();
            }
        }
    });
    t.start();
    threadThread.newThread(new Runnable()
    {
        @Override
        public void run()
        {
            int i = 0;
            while(i <410000)
            {
                list.op();
            }
        }
    }).start();

    threadThread.newThread(new Runnable()
    {
        @Override
        public void run()
        {
            for(int i=0;i<400000;i++)
            {
                boolean flag = list.offer("item" + i);
                if(!flag)
                {
                    System.out.println("添加元素失败");
                }
            }
            System.out.println(list.ee);
        }
    }).start();

    System.out.println("主线程结束");
}

}

多个线程去取阻塞队列为啥会有并发问题呢?i正常应该为400000的,谁能给解释下

解决方案

但是现在的值为402235

解决方案二:

 while(i <410000)
            {
synchronized (list) {
                       list.op();
                                            }
                     }

list没有做线程安全同步,使用synchronized进行安全处理。

时间: 2024-10-06 13:25:04

condition.await()并发问题的相关文章

ReentrantLock Condition await signal 专题

  Condition的执行方式,是当在线程T1中调用await方法后,线程T1将释放锁,并且将自己阻塞,等待唤醒, 线程T2获取到锁后,开始做事,完毕后,调用Condition的signal方法,唤醒线程T1,在t2执行完unlock后,线程T1恢复执行.  signalAll和signal很像,内部就是将Condition队列里所有的Node都加入到release队列中,仅此而已   代码如下: import org.joda.time.LocalDateTime; import java.

Java并发(三)使用显式的Lock和Condition对象

    在之前的Java并发(一)wait()与notifyAll()一文中的例子中,我们使用了wait()和notifyAll()来模拟了给汽车打蜡和抛光的情景.在JavaSE5中,还提供了java.util.concurrent.locks.Condition对象供我们使用.你可以在Condition上调用await()来挂起一个任务.当外部条件发生变化,意味着某个任务应该继续执行时,你可以通过调用signal()来通知这个任务,或者调用signalAll()来唤醒所有在这个Conditio

Java多线程与并发库高级应用

想快速精通多线程?看这里  http://blog.chinaunix.net/uid-540802-id-4431193.html 什么是线程         线程,是程序执行流的最小单元.是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可以与同属一个进程的其他线程共享进程所拥有的全部资源,一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行.在单个程序中同时运行多个线程完成不同的工作,称为多线程.当自己想

JAVA并发容器代码随读

1. java.util.concurrent所提供的并发容器 java.util.concurrent提供了多种并发容器,总体上来说有4类,队列类型的BlockingQueue和 ConcurrentLinkedQueue,Map类型的ConcurrentMap,Set类型的ConcurrentSkipListSet和CopyOnWriteArraySet,List类型的CopyOnWriteArrayList. 这些并发容器都采用了多种手段控制并发的存取操作,并且尽可能减小控制并发所带来的性

Java 高并发五:JDK并发包1详细介绍_java

在[高并发Java 二] 多线程基础中,我们已经初步提到了基本的线程同步操作.这次要提到的是在并发包中的同步控制工具. 1. 各种同步控制工具的使用 1.1 ReentrantLock ReentrantLock感觉上是synchronized的增强版,synchronized的特点是使用简单,一切交给JVM去处理,但是功能上是比较薄弱的.在JDK1.5之前,ReentrantLock的性能要好于synchronized,由于对JVM进行了优化,现在的JDK版本中,两者性能是不相上下的.如果是简

JAVA线程间协作:Condition

    内置条件队列存在一些缺陷.每个内置锁都只能有一个相关联的条件队列,因而在像BounderBuffer这种类中,多个线程可能在同一个条件队列上等待不同的条件谓词,并且在最常见的加锁模式下公开条件队列对象.这些因素都使得无法满足在使用notifyAll时所有等待线程为统一类型的需求.如果想编写一个带有多个条件谓词的并发对象,或者想获得除了条件队列可见性之外的更多控制权,就可以使用显示的Lock和Condition而不是内置锁和条件队列,这是一种更灵活的选择.     一个Condition和

Lock&amp;amp;Condition实现线程同步通信

import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ConditionCommunication {     final Business business = new Business();     public static void main(Stri

java.util.concurrent包(3)——线程间通信wait/notify和await/signal

一.线程如何停止 使用stop()不安全.它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们.结果很难检查出真正的问题所在.suspend()方法容易发生死锁.调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定.此时其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行.对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁.所以不应该使用suspend().正确的做

Java多线程编程中使用Condition类操作锁的方法详解_java

Condition的作用是对锁进行更精确的控制.Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法.不同的是,Object中的wait(),notify(),notifyAll()方法是和"同步锁"(synchronized关键字)捆绑使用的:而Condition是需要与"互斥