Java线程笔记(三)——张洪波《零基础轻松学java》

本文通过电话拨号的例子,探讨了在Java中线程同步的重要性。未同步的情况导致多个线程同时访问共享资源,造成不合理的行为。通过引入`synchronized`关键字,实现了线程间的互斥访问,确保了资源的正确使用。同步实例展示了如何使用`synchronized`避免并发问题,确保线程按预期顺序执行。
摘要由CSDN通过智能技术生成

                                        “做不到的承诺和撒谎没有什么区别。 ”


1.7线程同步

当多个线程共享同一个变量等资源时,需要确保资源在某一时刻只有一个线程占用,这个过程就是线程同步。信号量是同步中的一个重要概念。信号量是一个对象,也是互斥体。当一个线程进入互斥体,互斥体就会锁定,此时任何试图进入互斥体的线程都必须等待这个线程出来。

注:Java线程同步本身的复杂性决定了要正确处理线程同步不是一件容易的事情。

下面给出一个没有使用过线程同步的例子:

首先构造一个电话类,定义一个打电话的方法

public class PhoneCall {

    public static void call(String name) {

        try {
            System.out.println(name + "拨打电话");
            Thread.sleep(100);
            System.out.println(name + "正在通话中");
            Thread.sleep(100);
            System.out.println(name + "挂断电话");
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

然后构造一个调用电话类打电话方法的线程类。看一看一步电话在没有同步情况下的工作状态:

public class Call extends Thread{
    public Call(String arg0) {
        super(arg0);
    }

    @Override
    public void run() {
        PhoneCall.call(getName());
    }
}

最后在main方法里创建线程并调用:
 

public class Test {
    public static void main(String[] args) {

        Call first = new Call("First");
        Call second = new Call("Second");
        Call third = new Call("Third");
        first.start();
        second.start();
        third.start();
    }
}

执行结果为:

 从执行结果可以看出,First打电话的等待过程中,Second也拨打了电话,Second进入等待时,Third开始拨打电话。而且First最后才通话。这是不合理的,所以需要用到线程同步。

同步实例:相同的场景

构造一个电话类,定义一个打电话的方法

/**
 * @author asus
 */
public class PhoneCall {

    public synchronized static void call(String name) {

        try {
            System.out.println(name + "拨打电话");
            Thread.sleep(100);
            System.out.println(name + "正在通话中");
            Thread.sleep(100);
            System.out.println(name + "挂断电话");
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

 构造一个调用电话类打电话的线程类:

class SynCall extends Thread{

    public SynCall(String arg0){
        super(arg0);
    }

    @Override
    public void run() {
        PhoneCall.call(getName());
    }
}

最后定义main方法:

/**
 * @author asus
 */
public class Test {
    public static void main(String[] args) {

        SynCall first = new SynCall("First");
        SynCall second = new SynCall("Second");
        SynCall third = new SynCall("Third");
        first.start();
        second.start();
        third.start();
    }
}

执行结果如下:

First在拨打电话、通话、挂断电话后才能继续对Second进行下一操作这样才合理。 这个代码和上一个示例的代码,本质区别在于synchronized关键字。

此外使用synchronized(mutex){}同样可以实现同步。其中mutex就是互斥体,是一个对象。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

才疏学浅的小缘同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值