线程间通信

2020/08/14 102

多线程 synchronized

例子

线程间通信例子:两个线程交替打印数字。

Java

public class CommunicationTest {
    public static void main(String[] args) {
        var number = new Number();
        var t1 = new Thread(number);
        var t2 = new Thread(number);
        t1.setName("线程1");
        t2.setName("线程2");
        t1.start();
        t2.start();
    }
}

public class Number implements Runnable {
    private int number = 1;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                // 通知另外一个线程,可以激活了,但是这部分的代码块被锁定了,另外的线程执行不了。
                notify();
                if (number <= 100) {
                    System.out.println(Thread.currentThread().getName() + ": " + number);
                    number++;
                    try {
                        // 此操作会解锁
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
}

C#

class Program
{
    static readonly object _locker = new object();
    static int number = 1;

    static void Main(string[] args)
    {
        Parallel.For(0, 2, i =>
        {
            while (number < 100)
            {
                lock (_locker)
                {
                    Monitor.PulseAll(_locker);
                    Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}: {number}");
                    number++;
                    Monitor.Wait(_locker);
                }
            }
        });
    }
}

回顾

设计到三个方法:

注意:

  1. 上述方法全部要在 synchronized 代码块中或 synchronized 签名的方法中。
  2. 上述方法和 synchronized 要使用同一个对象,示例中给的是 this,也可以定义一个 object,但要确保一致。
  3. 上述三个方法是定义在 java.lang.Object 类中。

wait()sleep() 都会让当前线程阻塞,它们的不同之处是:

  1. sleep()Thread 类的静态方法,而 wait() 是 Object 类的成员
  2. sleep() 仅仅是线程休眠,随处可以使用,wait() 有使用上下文限制 synchronized
  3. 如果两个方法都在 synchronized 中使用,wait() 会释放🔒