您现在的位置是:首页 > 正文

java中线程同步(synchronized的用法)

2024-04-01 05:16:52阅读 1

多线程存在的问题

1.多线程会造成共享资源数据环混乱。因为,每一个线程都有自己的内存。当一个线程从公共资源读取数据后,保存到了自己线程的内存中,然后才执行。这样如果多个线程同时读取公共资源的数据,而没有手段去控制让这些线程排队,就会出现数据混乱的问题。
下面的代码为例子:是一个抢票的例子

package Lock;
//线程不安全实例1:共用对象
public class UnSaveTest1 implements Runnable{
	private int ticketNum=10;
	public  void  run() {
		while (ticketNum>=1) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了"+ticketNum--);
			
		}
	
	}
	
	public static void main(String args[]) {
		UnSaveTest1 test1=new UnSaveTest1();
		
		new Thread(test1,"李华").start();
		new Thread(test1,"张三").start();
		new Thread(test1,"黄牛").start();
	}
}

运行结果如下:
在run方法中,我们对票的数量(ticketNum)进行控制,只有票数大于0才能购买成功;理想的情况下,应该是每一个抢到的票都是不一样的。但是运行结果却显示:三个人中,存在两人抢到同一张票的情况,这就是线程引起的数据不安全问题。
在这里插入图片描述
下面我对上面的例子,做一下内存图分析,比如现在的票数是9
在这里插入图片描述
因此,便得到李华和黄牛党同时拿到第九张票的情况。

线程同步,解决多线程数据不安全问题

用法
1.给执行读取公共资源的的方法加上synchronized。在多线程并发的情况下,次机制会给公共的资源加上锁。当前线程进来后,就会上锁,不允许其他线程再进来了。每一次只能执行一个线程任务。只有当这个线程任务结束后,才能释放锁,下一个线程才能使用这个公众资源。
下面的代码例子:(注意 和上面run方法做对比)

package Lock;
//线程不安全实例1:共用对象,加锁排队解决问题
public class UnSaveTest1 implements Runnable{
	private int ticketNum=10;
	public synchronized void  run() {
		while (ticketNum>=1) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了"+ticketNum--);
			
		}
	
	}
	
	public static void main(String args[]) {
		UnSaveTest1 test1=new UnSaveTest1();
		
		new Thread(test1,"李华").start();
		new Thread(test1,"张三").start();
		new Thread(test1,"黄牛").start();
	}
}

运行结果如下:解决了两人抢到同一张票的情况
在这里插入图片描述
2.给公共资源的对象加锁
例子:两人同时向一张银行卡取现。公众资源是银行卡,我这个例子以Account类作为公共资源对象,在run方法里面使用的这个类的实例对象,在前面加上 修饰符synchronized ,然后在方法体执行操作,可以达到同样的目的。

package Lock;
//银行取钱例子
public class UnSaveTest2 extends Thread{
	Account account;
	private int amount;
	private String name;
	public UnSaveTest2(Account account,int amount,String name) {
		this.amount=amount;
		this.name=name;
		this.account=account;
	}
	public void run() {
		synchronized (this.account) {
		//给公共资源对象上锁
			this.drawMoney(this.amount, this.name);
		}
		
	}
	
	public void  drawMoney(int amount,String name) {
		
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(this.account.getAmount()>0&&amount<=this.account.getAmount()) {
			this.account.setAmount(this.account.getAmount()-amount);
			System.out.println(name+"取走了"+amount+"账户还剩下"+this.account.getAmount());
		}
	}
	
	public static void main(String args[]) {
		Account account=new Account(100, "住房基金");
		UnSaveTest2 t1=new UnSaveTest2(account, 60,"小红");
		UnSaveTest2 t2=new UnSaveTest2(account, 60,"小名");
		t1.start();
		t2.start();
		
	}
}

//银行账户
class Account{
	private int amount;
	private String name;
	public Account(int amount,String name) {
		this.amount=amount;
		this.name=name;
	}
	
	public void  setAmount(int amount) {
		this.amount=amount;
	}
	public int getAmount() {
		return this.amount;
	}
}

加上锁运行结果如下:当小红和小甘同时取钱的时候,双方金额都为60万,加起来为120万大于银行存款100万。因此正常逻辑是不能同时满足二人的取款总额。最后,小红取走了60万,小甘取款就会失败。
在这里插入图片描述
但是,没有加上锁之前,运行结果是这样的,双方都能取到钱。如果不加以控制,那银行不是得倒闭了吗,哈哈哈哈。
在这里插入图片描述

synchronized 使用会影响性能

我们为了控制并发,加上synchronized ,给线程排队,并对资源加锁。在加锁和解锁的时候,需要消耗一定的时间和内存,因此,这个是不可避免的。

网站文章

  • java解惑--谜题14:转义字符的溃败

    谜题14:转义字符的溃败 摘自《java解惑》一书,下载地址:http://download.csdn.net/detail/itismelzp/9407769 下面的程序使用了两个Unicode 的转义字符,它们是用其十六进制代码来表示 Unicode 字符。那么,这个程序会打印什么呢? public class EscapeRout{ public s

    2024-04-01 05:16:44
  • 高级会计职称计算机考什么,会计高级职称考哪些科目

    还不清楚会计高级职称考哪些科目的小伙伴,赶紧过来瞧瞧吧!下面由出国留学网小编为你精心准备了“会计高级职称考哪些科目 评审条件是什么”,本文仅供参考,持续关注本站将可以持续获取更多的资讯!会计高级职称考...

    2024-04-01 05:16:04
  • Python学习(三):class struct : pass 数据结构

    注意此处的TxPDU具备了数据结构的属性,下面就可以定义为。创建一个一次性&quot;struct&quot;对象来保存各种状态标志。这部分就看自己怎么实现定义了,想要的属性均可添加。

    2024-04-01 05:15:57
  • 2.2 ES Module模块化的原理

    2.2 ES Module模块化的原理

    ES Module的原理ES Module和CommonJS的区别一、CommonJS模块加载js文件的过程是运行时加载的,并且是同步的:运行时加载意味着是js引擎在执行js代码的过程中加载 模块;同...

    2024-04-01 05:15:50
  • 基于python的随机森林回归实现_基于Scikit-Learn机器学习库的随机森林模型优化调参流程...

    基于python的随机森林回归实现_基于Scikit-Learn机器学习库的随机森林模型优化调参流程...

    因为有Scikit-Learn这样的库,现在用Python实现任何机器学习算法都非常容易。随机森林是一个由众多决策树构建的集成学习算法模型。随机森林模型的介绍,百度搜索,会出现一大堆,这里不再赘述。这...

    2024-04-01 05:15:10
  • Vue3+Ts+Vite项目(第十三篇)——配置Element-Plus主题色

    Vue3+Ts+Vite项目(第十三篇)——配置Element-Plus主题色

    找了很多博客,总结出来的最有效的vue3+ts+vite项目配置element-plus组件主题色

    2024-04-01 05:15:02
  • java 数组 push pop_JavaScript学习笔记:数组的push()、pop()、shift()和unshift()方法

    java 数组 push pop_JavaScript学习笔记:数组的push()、pop()、shift()和unshift()方法

    JavaScript是一种弱类型语言,不像其它程序语言需要严格定义数据类型。在JavaScript中数组可以任意修改变动,这样也就出现了一个问题,如果边遍历数组边操作数组(比如删除当前项,则所有之后的...

    2024-04-01 05:14:56
  • 51Talk-Level 7 Unit 5 L2

    今日主题:保守秘密(keeping a secret )高频口语句型(想到中文但是不能马上联想到英文的):1. break up with somebody 与某人绝交2. lie to somebody 向某人说谎3. be tempted to do something 想做某事4. look up to 羡慕,尊敬5

    2024-04-01 05:14:50
  • leetcode:149. 直线上最多的点数

    题目: 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。 示例 1: 输入: [[1,1],[2,2],[3,3]] 输出: 3 解释: ^ | | o | o | o ±------------&gt; 0 1 2 3 4 示例 2: 输入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]] 输出: 4 解释: ^ ...

    2024-04-01 05:14:11
  • 高性能(二)

    高性能(二)

    高性能(二)

    2024-04-01 05:14:04