线程的同步
发布日期:2022-02-06 00:27:00 浏览次数:28 分类:技术文章

本文共 2338 字,大约阅读时间需要 7 分钟。

多线程共享数据引发的问题

用一个简单的例子来说,就是我们经常遇到的过年抢车票的问题,以前人们是去车站排队,先到先得,现在随着互联网的发展,我们可以在网上购票了,现在我们使用多线程来模拟抢票过程,每个人机会一样。

关键代码如下:

/** * 线程不安全的网络抢票 * */public class Site implements Runnable{	private int count=10;  //记录剩余票数		private int num = 0;   //记录买到第几张票	public void  run(){		while(true){			//没有余票时,跳出循环			if(count<=0){				break;			}			//第一步:修改数据			num++;			count--;			try {				Thread.sleep(500); //模拟网络延时			} catch (InterruptedException e) {							e.printStackTrace();			}						//第二步:显示信息			System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票!");					}	}}//测试类public class Test {	public static void main(String[] args) {		Site site = new Site();		Thread person1= new Thread(site,"桃跑跑");		Thread person2= new Thread(site,"抢票代理");		Thread person3= new Thread(site,"黄牛党");		System.out.println("********开始抢票********");		person1.start();		person2.start();		person3.start();	}}

在这里插入图片描述

看结果显示如下问题:
不是从第一张票开始
存在多人抢到一张票的情况
有些票号没有被抢到

这些都是由于多个线程并发操作统一共享资源,带来的数据不安全问题,要解决这样的问题,我们就需要使用到线程同步。

线程同步的实现

什么是线程同步
当两个或多个线程需要访问同一资源时,需要以某种顺序来确保该资源某一时刻只能被一个线程使用,这就是线程同步

采用线程同步来控制线程的执行有两种方式,即同步带吗方法和同步代码块。这两种方法都是用synchronized关键字实现。

通过在方法申明中加入synchronized关键字实现同步方法,其语法如下:

访问修饰符 synchronized 返回类型 方法名(参数列表){//省略方法体…}
或者
synchronized 访问修饰符 返回类型 方法名(参数列表){//省略方法体…}

在语法中:

synchronized是同步关键字
访问修饰符是指public,private等。

使用同步方法解决上述代码,如下所示:

public class Site implements Runnable{	private int count=10;  //记录剩余票数		private int num = 0;   //记录买到第几张票	public void  run(){		while(true){			if(count<=0){				break;			}			//第一步:修改数据			num++;			count--;			try {				Thread.sleep(500); //模拟网络延时			} catch (InterruptedException e) {							e.printStackTrace();			}						//第二步:显示信息			System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票!");					}	}}

同步方法的缺陷

如果将一个运行时间较长的方法声明称synchronized将会影响效率

同步代码块

语法:synchronized(syncObject){
//需要同步的代码
}
示例代码如下:

public class Site implements Runnable {	private int count = 10; // 记录剩余票数	private int num = 0; // 记录买到第几张票	public void run() {		while (true) {			//同步代码块			synchronized (this) {				// 没有余票时,跳出循环				if (count <= 0) {					break;				}				// 第一步:修改数据				num++;				count--;				try {					Thread.sleep(500); // 模拟网络延时				} catch (InterruptedException e) {					e.printStackTrace();				}				// 第二步:显示信息				System.out.println(Thread.currentThread().getName() + "抢到第"						+ num + "张票,剩余" + count + "张票!");			}		}	}}

转载地址:https://blog.csdn.net/weixin_46175284/article/details/105546381 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:JAVA的多线程和Native的用法
下一篇:uniapp公众号禁止调整字体大小

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月23日 05时16分41秒