多线程02

简介: 多线程02

1.线程安全问题及解决.

1.1线程安全问题介绍.

  • 当我们使用多个线程访问同一资源(可以是同一个变量、同一个文件、同一条记录等)的时候,若多个线程只有读操作,那么不会发生线程安全问题。但是如果多个线程中对资源有读和的操作,就容易出现线程安全问题。
  • 举例:


1.2线程安全问题案例演示-卖票.

  • 案例:火车站要卖票,我们模拟火车站的卖票过程。因为疫情期间,本次列车的座位共100个(即,只能出售100张火车票)。我们来模拟车站的售票窗口,实现多个窗口同时售票的过程。注意:不能出现错票、重票。
  • 分析,采用哪种线程实现方式?
  • 分析一:多个窗口(线程)共同卖100张票,也就是多个线程做同样的一件事情:卖这100张票。线程和线程之间数据是共享的,采用实现Runnable接口方式实现线程。
  • 分析二:采用继承Thread类方式也可以实现,需要在线程类里面把票的总量定义成静态的全局变量:static int piao = 100.
  • 通过实现Runnable接口方式实现该案例:

  • 运行结果如下:

  • 从结果上可以发现,出现了一票多卖的情况,这是多条线程在同一时间访问同一资源的原因造成的【资源访问冲突】,也就是线程安全问题。

1.3同步机制解决线程安全问题.

  • 线程同步,即:排队。
  • 要解决上述多线程并发访问一个资源的安全性问题:也就是解决重复票与不存在票问题,Java中提供了同步机制(synchronized)来解决。如下图所示:

  • 窗口1线程进入操作的时候,窗口2和窗口3线程只能在外等着,窗口1操作结束,窗口1和窗口2和窗口3才有机会进入代码去执行。也就是说在某个线程修改共享资源的时候,其他线程不能修改该资源,等待修改完毕同步之后,才能去抢夺CPU资源,完成对应的操作,保证了数据的同步性,解决了线程不安全的现象。
  • 为了保证每个线程都能正常执行原子操作,Java引入了线程同步机制。注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着(blocked:封锁的/闭塞的/阻塞/堵塞)。

1.4同步机制解决线程安全问题的原理.

  • 同步机制的原理,其实就相当于给某段代码加“锁”,任何线程想要执行这段代码,都要先获得“锁”,我们称它为同步锁。
  • 因为Java对象在堆中的数据分为分为对象头、实例变量、空白的填充。而对象头中包含:
  1. Mark Word:记录了和当前对象有关的GC、锁标记等信息。
  2. 指向类的指针:每一个对象需要记录它是由哪个类创建出来的。
  3. 数组长度(只有数组对象才有)。
  • 哪个线程获得了“同步锁”对象之后,”同步锁“对象就会记录这个线程的ID,这样其他线程就只能等待了,除非这个线程”释放“了锁对象,其他线程才能重新获得/占用“同步锁”对象。

1.5同步代码块和同步方法.

1.5.1同步代码块.

  • 同步代码块:synchronized 关键字可以用于某个区块前面,表示只对这个区块的资源实行互斥访问。
  • 语法如下:

  1. 同步锁:里的参数是同步监视器,俗称“同步锁”。同步锁必须一个唯一的对象(可以是常量,但不能是静态的常量),多条线程必须公用一把锁。如何判断对象是唯一的?比如可以在Runnable匿名实现类里面定义一个 Object obj = new Object();对象,然后 obj对象就可以作为同步锁。对象obj是唯一的前提条件是,obj对象所在的类只被实例化了一次,如果实例化多次,那么 obj对象就不是唯一的了。如果为了方便,不想再重新定义一个唯一的对象,可以采用 this对象作为同步锁,this对象代表调用当前方法的对象。
  2. 被同步的代码:需要被同步的代码指的是,操作共享数据的代码;
  3. 共享数据是:多个线程共同操作的变量。
  • 通过同步代码块解决卖票案例问题:

  • 注1:while循环不能被锁。分析:如果while循环也被锁了,那么第一个拿到锁的线程就会不停的卖票,直到把票卖完,这样100张票就会被第一个抢到锁的线程卖完(代码验证)。
  • 注2:这里的同步锁 this代表调用当前 run方法的对象,也就是 runnable对象,该对象只被创建了一个,是唯一的,满足同步锁的要求。

1.5.2同步方法.

  • 同步方法:synchronized 关键字直接修饰方法,表示同一时刻只有一个线程能进入这个方法,其他线程在外面等着。
  • synchronized 锁住的方法,同步锁是 this对象,this对象代表调用当前方法的对象。
  • 语法如下:

  • 通过同步方法方式解决卖票案例问题:

  • 测试


相关文章
|
消息中间件 前端开发
C++11多线程相关
C++11多线程相关
81 0
|
1月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
44 1
C++ 多线程之初识多线程
|
6月前
|
Web App开发 IDE Java
什么是多线程
什么是多线程
46 3
|
6月前
|
安全 Java C++
多线程问题(四)
多线程问题(四)
39 0
|
6月前
|
安全 Java C#
C#多线程详解
C#多线程详解
59 0
|
11月前
|
安全 Linux C++
C++多线程
C++多线程
54 1
|
安全 Linux C++
C++多线程实现
C++11支持语言级别的多线程编程,可以跨平台运行,支持windows/linux/mac等。
113 0
|
安全 C++
C++多线程(二)
C++多线程
148 0
|
Linux API 调度
C++之多线程(一)
C++进阶之多线程上
121 0