java - Java中线程间的通信无锁

标签 java multithreading conditional-statements reentrantlock

所以我想要实现的是两个线程轮流执行他们的任务。我本来只有一个问题;

  1. 如何在不使用锁的情况下实现两个线程轮流执行任务?我不想要锁的原因是因为我觉得很愚蠢,当两个线程尝试访问的公共(public)资源没有时使用锁。

所以我打算制作一个代码的小示例,然后我发现即使使用锁我也无法使其工作。所以我的第二个问题是;我如何使代码按预期工作?在我看来,它应该可以工作,但这只是我:)

  1. 线程1打印消息
  2. 线程 1 发出信号,表明线程 2 可以打印消息
  3. 线程2打印消息
  4. 线程 2 发出信号,表明线程 1 可以重新开始

public class App {

    Lock lock = new ReentrantLock();
    Condition cond1 = lock.newCondition();
    Condition cond2 = lock.newCondition();

    public App() {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        lock.lock();
                        System.out.println("Thread 1");
                        cond2.signalAll();
                        cond1.await();
                        lock.unlock();
                    }
                } catch (InterruptedException e) {
                }
            }
        });
        thread1.start();

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        lock.lock();
                        cond2.await();
                        System.out.println("           Thread 2");
                        cond1.signalAll();
                        lock.unlock();
                    }
                } catch (InterruptedException e) {
                }
            }
        });
        thread2.start();
    }

    public static void main(String[] args) {
        new App();
    }

}

最佳答案

(1) await() 通常用在循环中;不这样做是错误的迹象。

while( some condition not met )
    cond.await();

(2) unlock() 应该位于 finally block 中

(3) signal() 仅向当前等待的线程发出信号;如果没有线程等待,信号就会丢失。

    lock.lock();
    cond.signal(); // lost
    cond.await();  // won't wake up

(4) 对于像这样的简单情况,使用良好的旧 synchronized 并没有什么错。实际上,在使用更多“高级”东西之前,您最好先了解它。

(5)解决方案:

    Lock lock = new ReentrantLock();
    Condition cond = lock.newCondition();
    int turn=1; // 1 or 2


    // thread1

            lock.lock();
            try
            {
                while (true)
                {
                    while(turn!=1)
                        cond.await();
                    System.out.println("Thread 1");
                    turn=2;
                    cond.signal();
                }
            }
            finally
            {
                lock.unlock();
            }

    // thread2
    // switch `1` and `2`

(6) 一圈线程,每个线程唤醒下一个

    int N = 9;
    Thread[] ring = new Thread[N];
    for(int i=0; i<N; i++)
    {
        final int ii = i+1;
        ring[i] = new Thread(()->
        {
            while(true)
            {
                LockSupport.park();   // suspend this thread
                System.out.printf("%"+ii+"d%n", ii);
                LockSupport.unpark(ring[ii%N]);  // wake up next thread
                // bug: spurious wakeup not handled 
            }
        });
    }

    for(Thread thread : ring)
        thread.start();

    LockSupport.unpark(ring[0]);  // wake up 1st thread

关于java - Java中线程间的通信无锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30541258/

相关文章:

java - jndi-name 属性覆盖 - JUnit - Spring - Struts 集成测试

javascript - 为什么我的条件标签在 Blogger 帖子中不起作用

javascript - 从 for 循环中的函数返回值

c - 在二维数组的一行上运行的并行化函数(C、OpenMP、CilkPlus)

c - 初始化 Apache 服务器中的全局变量

Python 写入 .txt 文件

java - apachetiles 2 和 JSP 的问题

java - mongodb中如何通过某些条件获取字段的最大值

java - 带有 token 存储的 CXF 自定义安全 token 提供商

c# - 如何对客户端网络代码进行单元测试?