java线程间通讯、synchronized和reentrantLock实现资源控制

需求:请用线程1、2分别打印1-26,A-Z,要求打印效果是1A2B3C…26Z
需求分析:需要完成线程间交替执行,必须实现线程间通讯+锁才能完成
需求实现:下面我分别使用synchronized 和 reentrantLock 两种锁机制来分别实现,见如下代码

一、使用synchronized实现

public class SynchronizedTest {
    /**
     * 作为锁对象
     */
    private static Object object = new Object();
    /**
     * 控制t1优先t2获取object锁
     */
    private static boolean flag;

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 26; i++) {
                synchronized (object) {
                    flag = true;
                    System.out.print(i);
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    object.notify();
                }
            }
            System.out.print("\n<thread 1 finish>");
        });

        Thread t2 = new Thread(() -> {
            while (!flag) {
                System.out.println("wait thread 1");
            }
            for (int i = 'A'; i <= 'Z'; i++) {
                synchronized (object) {
                    object.notify();
                    System.out.print((char) i);
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
            System.out.print("\n<thread 2 finish>");

        });

        t1.setName("<#1>");
        t2.setName("<#2>");
        t1.start();
        t2.start();
        t2.join();
        t1.join();
        System.out.println("\nall thread finsh");

    }


}

执行结果:

1A2B3C4D5E6F7G8H9I10J11K12L13M14N15O16P17Q18R19S20T21U22V23W24X25Y26Z
<thread 1 finish>
<thread 2 finish>
all thread finsh

二、使用reentrantLock实现

public class LockTest {

    private static ReentrantLock reentrantLock = new ReentrantLock();
    private static Condition condition = reentrantLock.newCondition();
    private static volatile boolean flag;

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(() -> {
            try {
                reentrantLock.lock();
                flag = true;
                for (int i = 1; i <= 26; i++) {

                    System.out.print(i);
                    condition.await();
                    condition.signal();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                reentrantLock.unlock();
                System.out.print("\n<thread 1 finish>");
            }
        });


        Thread t2 = new Thread(() -> {

            try {
                while (!flag) {
                    System.out.println("wait thread 1");
                }
                reentrantLock.lock();
                for (int i = 'A'; i <= 'Z'; i++) {
                    condition.signal();
                    System.out.print((char) i);
                    condition.await();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                reentrantLock.unlock();
                System.out.print("\n<thread 2 finish>");
            }

        });
        t1.setName("#1");
        t2.setName("#2");
        //用flag变量做了限制,必须等t1线程先拿到lock锁
        t2.start();
        t1.start();
        t1.join();
        t2.join();
        System.out.println("\nall thread finish");
    }

}

执行结果:

wait thread 1
1A2B3C4D5E6F7G8H9I10J11K12L13M14N15O16P17Q18R19S20T21U22V23W24X25Y26Z
<thread 1 finish>
<thread 2 finish>
all thread finish

以上两个执行结果中第一行的差异是因为 t1、t2在启动执行顺序不一样,这t1.start();t2.start();这两行代码执行顺序也不固定的(可能重排序),退一万步讲,及时执行顺序固定,t1,t2线程执行顺序也不确定的(取决于系统cpu时间片的分配)

总结:

线程间通讯的两大方法:
1、通过主内存通讯
如volatile关键字,带有volatile关键字的变量只要发生写操作,其他读这个变量的线程均能立刻感知
volatile的特性是:1、线程修改变量后必须立刻刷新到主内存 2、禁止重排序(线程间遵守happen before原则)
2、通过wait()/notify()方法相互通讯

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值