如何在java中使用线程时安全地增加

时间:2014-08-10 18:04:20

标签: java multithreading thread-safety critical-section

大家好,我想知道我是否可以得到一些建议我试图编写一个程序,可以计算有多少线程正在等待处理一个函数,然后一旦达到某个数字就会释放所有线程。但我的问题是我不能正确地增加,因为我可以同时处理增量代码,因此根本不会增加它。

protected synchronized boolean isOpen()
{
    //this code just calls mymethod intrested where the problem lies

  lock.interested();
    while(!lock.isReady())
    {
    }
    return true;// this statement releases all my threads

 }



public synchronized void  interested()
{

    count++;// how do i make this increment correctly with threads
    System.out.println(count+"-"+ lanes+"-"+ThreadID.get());
    if(count==lanes)
    {

        count =0;
        ready =true;
    }

}

3 个答案:

答案 0 :(得分:1)

您的方法的问题是一次只有一个线程可以进入synchronized方法,因此,您将永远不会继续,因为除了第一个线程之外的所有线程都在等待进入synchronized方法而第一个线程正在执行忙等待循环。您必须使用wait,它不仅可以解决繁忙等待的CPU周期浪费,还可以释放synchronized代码的相关锁,以便下一个线程可以继续:

protected synchronized boolean isOpen()
{
    lock.interested();
    while(!lock.isReady())
    {
        wait(); // now the next thread can enter isOpen()
    }
    notify(); // releases the previous thread wait()ing in this method
    return true;
 }

但是,请注意,由于您的代码被分割为多个不同的对象,因此这种方式非常不可靠。强烈建议将维护计数器的代码和实现等待计数器的代码放入一个对象中,以便在同一个锁下运行。您的代码结构必须确保无法在interested()实例上调用lockisOpen没有注意到。从您发布的两个代码片段中,无法推断是否是这种情况。

答案 1 :(得分:0)

  

编写一个可以计算等待线程数的程序   处理一个函数,然后一旦达到一定数量就可以了   释放所有线程

一个好的解决方案是使用CountDownLatch

从手册:

  

使用给定计数初始化CountDownLatch。等待方法   阻止,直到当前计数由于调用而达到零   countDown()方法,之后释放所有等待的线程   任何后续的等待调用立即返回。这是一个   一次性现象 - 计数无法重置。如果你需要一个   重置计数的版本,请考虑使用CyclicBarrier。

您可以找到一个好的代码示例here

答案 2 :(得分:0)

You should not use synchronised. Because only one thread will acquire monitor at a time.

您可以使用CountDownLatch。只需在初始化CountDownLatch时定义线程数。

private CountDownLatch countDownLatch = new CountDownLatch(no_of_threads);
protected  boolean isOpen()
{
    //this code just calls mymethod intrested where the problem lies

    countDownLatch.countDown();
    countDownLatch.await();
    return true;// this statement releases all my threads
 }


  All the threads are waiting in countDownLatch.await(). Once the required amount of thread comes(countDownLatch.countDown() is called) it will allow to proceed.