Java多线程同步

本文介绍了Java中实现线程同步的三种方式:Synchronized配合wait/notifyAll,ReentrantLock配合await/signalAll,以及park/unpark。通过实例展示了如何使用这些机制保证线程按顺序执行。
摘要由CSDN通过智能技术生成

        多线程总是异步执行,但是在某些情况下,一个线程需要等待另一个线程执行完成后才能执行,这就是线程的同步。在Java中有多种API可以实现线程的同步,接下来就介绍几种线程同步方式。

Synchronized
public class Synchronization {

    /**
     * 三个线程按顺序打印10次abc
     * flag为1,print1线程打印a,flag为2,print2线程打印b,flag为3,print3线程打印c
     */


    public static void main(String[] args) {

        Print print1 = new Print("a", 1, 2);
        Print print2 = new Print("b", 2, 3);
        Print print3 = new Print("c", 3, 1);
        print1.start();
        print2.start();
        print3.start();

    }

}

class Print extends Thread{

    // flag和lock作为静态变量,表示所有线程共享的属性
    private static int flag = 1;
    private static Object lock = new Object();

    private String content;
    private int currFlag;
    private int nextFlag;

    public Print(String content,int currFlag, int nextFlag){
        this.content = content;
        this.currFlag = currFlag;
        this.nextFlag = nextFlag;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            synchronized (lock){
                while(flag != currFlag){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print(content);
                flag = nextFlag;
                lock.notifyAll();
            }
        }
    }
}

        Synchronized配合wait方法使线程等待,notifyAll唤醒所有线程,注意如果flag!=currFlag,线程等待,当线程被唤醒并获取到锁,将继续往下执行,所以需要使用while循环判断,如果使用if,被唤醒并获取到锁时,将会直接执行打印语句。

Reentrantlock
public class Synchronization {

    /**
     * 三个线程按顺序打印10次abc
     * flag为1,print1线程打印a,flag为2,print2线程打印b,flag为3,print3线程打印c
     */


    public static void main(String[] args) {

        Print print1 = new Print("a", 1, 2);
        Print print2 = new Print("b", 2, 3);
        Print print3 = new Print("c", 3, 1);
        print1.start();
        print2.start();
        print3.start();

    }

}

class Print extends Thread{

    // flag和lock作为静态变量,表示所有线程共享的属性
    private static int flag = 1;
    private static ReentrantLock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();


    private String content;
    private int currFlag;
    private int nextFlag;

    public Print(String content,int currFlag, int nextFlag){
        this.content = content;
        this.currFlag = currFlag;
        this.nextFlag = nextFlag;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            lock.lock();
            try {
                while(currFlag != flag){
                    condition.await();
                }
                System.out.print(content);
                flag = nextFlag;
                condition.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}

        Reentrantlock配合await方法使线程等待,signalAll唤醒所有线程,同理如果flag!=currFlag,线程等待,当线程被唤醒并获取到锁,将继续往下执行,所以需要使用while循环判断,如果使用if,被唤醒并获取到锁时,将会直接执行打印语句。注意一个Reentrantlock对象可以创建多个Condition,这个Condition相当于阻塞队列。使用多个Condition同样也可以完成线程的同步,这里就不再展开阐述。

park与unpark
public class Synchronization {

    /**
     * 三个线程按顺序打印10次abc
     */


    public static void main(String[] args) {

        Print print1 = new Print("a");
        Print print2 = new Print("b");
        Print print3 = new Print("c");
        print1.setNextThread(print2);
        print2.setNextThread(print3);
        print3.setNextThread(print1);
        print1.start();
        print2.start();
        print3.start();
        LockSupport.unpark(print1);

    }

}

class Print extends Thread{

    private String content;
    private Thread nextThread;

    public Print(String content){
        this.content = content;
    }

    public void setNextThread(Thread nextThread) {
        this.nextThread = nextThread;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            LockSupport.park();
            System.out.print(content);
            LockSupport.unpark(nextThread);
        }
    }
}

        park和unpark的思路就是上来开启所有线程时,先将所有的线程进入等待状态,之后打开输出a的线程print1,print1输出a,之后唤醒打印b的print2线程,此时print1并没有进入等待,而是进入下一轮循环,调用了park方法而等待。

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值