线程的同步
程序员文章站
2024-03-01 18:49:52
...
多线程共享数据引发的问题
用一个简单的例子来说,就是我们经常遇到的过年抢车票的问题,以前人们是去车站排队,先到先得,现在随着互联网的发展,我们可以在网上购票了,现在我们使用多线程来模拟抢票过程,每个人机会一样。
关键代码如下:
/**
* 线程不安全的网络抢票
*
*/
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 + "张票!");
}
}
}
}
上一篇: Pytorch学习笔记-第五章
下一篇: 前端面试题——10.谈谈你对BFC的理解