线程的同步,什么时候释放锁,用什么语句可以停下当前线程?

一、先看两个类

1 、Ticket ,它实现了Runnable接口

package thread;

public class Ticket implements Runnable{

    private int tick=100;


    @Override
    public void run() {
        try {
            printTick();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void printTick() throws InterruptedException {
        while (true){
            if (tick>0){
                System.out.println(Thread.currentThread().getName()+"---tick为:  "+tick--);
            }else {
                break;

            }
        }
    }
}

2 、测试类

package thread;

public class Test01 {

    public static void main(String[] args) {
        Ticket ticket=new Ticket();

		//创建三个线程
        Thread thread1=new Thread(ticket);
        Thread thread2=new Thread(ticket);
        Thread thread3=new Thread(ticket);
		//为三个线程起名字
        thread1.setName("tick窗口1");
        thread2.setName("tick窗口2");
        thread3.setName("tick窗口3");
		//start线程,让这三个线程到就绪状态(线程的状态) 
        thread1.start();
        thread2.start();
        thread3.start();


    }
}

执行测试类Test1 的 main函数,执行结果:

在这里插入图片描述

此时线程是不安全的,多个线程访问同一个资源(ticket对象里的属性tick),可能线程一执行到中间某个时刻,线程二就进来访问了同一个资源。
如果线程一在改数据之前,线程二就访问了数据,此时线程一和线程二的拿到的数据是一样的,但在线程一执行完数据的修改操作后,这时线程一和线程二拿到的数据就不一样了,也就是不同步。
也就会出现上面的运行结果。

二、那怎么让它同步?

  • 用锁,同一个资源的多个线程共用一把锁。
  • 对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。
  • 在代码上的体现就是把public void printTick() throws InterruptedException 方法改为public synchronized void printTick() throws InterruptedException
package thread;

public class Ticket implements Runnable{

    private int tick=100;


    @Override
    public void run() {
        try {
            printTick();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void printTick() throws InterruptedException {
        while (true){
            if (tick>0){
                System.out.println(Thread.currentThread().getName()+"---tick为:  "+tick--);
            }else {
                break;

            }
        }
    }
}

这次的运行结果:
在这里插入图片描述

从结果上看是线程安全了,但是只有一个线程在执行,为什么?

因为线程一执行之后一直拿着锁,没有释放。

三、怎么才能让线程一释放锁?

1. 当前线程的同步方法、同步代码块执行结束后,会释放锁

我们把while循环拿掉,这样就可以演示这种情况。

package thread;

public class Ticket implements Runnable{

    private int tick=100;
    
    @Override
    public void run() {
        try {
            printTick();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void printTick() throws InterruptedException {
            if (tick>0){
                System.out.println(Thread.currentThread().getName()+"---tick为:  "+tick--);
            }
        
    }
}

while循环拿掉后的运行结果:
在这里插入图片描述

2.当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁。

package thread;

public class Ticket implements Runnable{

    private int tick=100;

    @Override
    public void run() {
        try {
            printTick();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void printTick() throws InterruptedException {
        while (true){
            if (tick>0){
                System.out.println(Thread.currentThread().getName()+"---tick为:  "+tick--);
                wait(10);
            }else {
                break;
            }
        }
    }


}

加wait(20);掉后的运行结果:

这次就可以看到线程的切换了

四、不会释放锁的操作:

线程执行同步代码块或同步方法时,程序调用Thread.sleep()、
Thread.yield()方法暂停当前线程的执行

package thread;

public class Ticket implements Runnable{

    private int tick=100;

    @Override
    public void run() {
        try {
            printTick();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void printTick() throws InterruptedException {
        while (true){
            if (tick>0){
                System.out.println(Thread.currentThread().getName()+"---tick为:  "+tick--);
                Thread.sleep(2000);
//                Thread.yield();
            }else {
                break;
            }
        }
    }
}

有Thread.sleep(2000);执行的结果:
有Thread.sleep(2000);执行的结果
有Thread.yield();执行的结果:
在这里插入图片描述
这两种情况都是只有一个线程在运行,就是不释放锁,不让其他线程参与进来。

有问题欢迎批评指教

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值