当多个线程同时共享同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。 举个案例来说:现在有100张火车票,有两个窗口同时抢火车票,使用多线程模拟抢票效果。 运行结果: 一号窗口和二号窗口同时出售第一张和第七张火车票,部分火车票会重复出售。 结论发现:多个线程共享同一个全局成员变量时,做写的操作可能会发生数据冲突问题。 使多线程之间同步或使用锁(lock) 将可能会发生数据冲突问题(线程不安全问题)的代码,只让当前一个线程进行执行。代码执行完成后释放锁,释放之后才能让其他线程执行,这样就可以解决线程不安全问题。 当多个线程共享同一个资源,而不会受到其他线程的干扰。 第一种:使用同步代码块 什么是同步代码块? 同步代码块就是将可能会发生线程安全问题的代码给包裹起来 第二种:使用同步函数 什么是同步函数? 使用synchronized 修饰的函数称为同步函数 动脑筋思考一下,同步函数使用的是什么锁?怎样证明呢? 同步函数使用this锁 证明方式: 一个线程使用同步代码块(this明锁),另一个线程使用同步函数。如果两个线程能实现同步,说明同步函数使用的是this锁。 第三种:使用静态同步函数 什么是静态同步函数? 同步函数上加上static关键字修饰或者使用线程类.class文件字节码 再动脑筋思考一下,同步函数使用的是什么锁?怎样证明呢? 静态同步函数使用的锁是当前线程类的字节码文件 证明方式: 一个线程使用当前线程类的字节码文件,另一个线程使用静态同步函数。如果两个线程能实现同步,说明静态同步函数使用的锁是当前线程类的字节码文件。 什么是多线程死锁? 同步中嵌套同步,锁没有来得及释放,一直等待,就会导致死锁。 下面就拿买火车票来演示一下死锁问题: 那么怎样可以避免死锁呢? 最好的方法就是不要在同步中嵌套同步1、什么是线程安全?
/** * @classDesc: 功能描述:(多线程之买火车票案例-展示线程不安全问题) */ class ThreadTrain implements Runnable { // 这是货票总票数,多个线程会同时共享资源 private int trainCount = 100; @Override public void run() { while (trainCount > 0) { //循环是指线程不停的去卖票 try { // 等待100毫秒 Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } sale(); } } /** * @methodDesc: 功能描述:(出售火车票) */ public void sale() { if (trainCount > 0) { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "出售第" + (100 - trainCount + 1) + "张票"); trainCount--; } } } public class ThreadDemo { public static void main(String[] args) { //创建一个实例 ThreadTrain threadTrain = new ThreadTrain(); //创建多个线程必须要用同一个实例,因为要共享全局变量 Thread thread1 = new Thread(threadTrain, "一号窗口"); Thread thread2 = new Thread(threadTrain, "二号窗口"); thread1.start(); thread2.start(); } }
2、如何解决多线程之间线程安全问题?
3、为什么使用线程同步或使用锁能解决线程安全问题呢?
4、什么是多线程之间同步?
5、我们该如何解决多线程安全问题?
private Object obj = new Object();// 自定义多线程同步锁 public void sale() { synchronized (obj ) { if (trainCount > 0) { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "出售第" + (100 - trainCount + 1) + "张票"); trainCount--; } } }
public synchronized void sale() { if (trainCount > 0) { try { Thread.sleep(40); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "出售第" +(100 - trainCount + 1) + "张票"); trainCount--; } }
public static synchronized void sale() { if (trainCount > 0) { try { Thread.sleep(40); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "出售第" + (100 - trainCount + 1) + "张票"); trainCount--; } }
6、多线程死锁问题
class ThreadTrain implements Runnable { // 这是总票数,多个线程会同时共享资源 private int trainCount = 100; public boolean flag = true; private Object obj= new Object(); @Override public void run() { if (flag) { while (trainCount > 0) { synchronized (obj) { //锁(同步代码块)在什么时候释放? 代码执行完会自动释放锁 //如果flag为true 先拿到 obj锁,再拿到this锁才能执行 //如果flag为false先拿到this,再拿到obj锁才能执行 sale(); } } } else { while (trainCount > 0) { sale(); } } } /** * @methodDesc: 功能描述:(出售火车票) */ public synchronized void sale() { synchronized (obj) { if (trainCount > 0) { try { Thread.sleep(40); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "出售第" + (100 - trainCount + 1) + "张票"); trainCount--; } } } } public class DeadlockThread { public static void main(String[] args) throws InterruptedException { ThreadTrain threadTrain = new ThreadTrain(); // 创建一个实例 Thread thread1 = new Thread(threadTrain, "一号窗口"); Thread thread2 = new Thread(threadTrain, "二号窗口"); //此时flag=true,线程thread1执行synchronized代码块,拿到obj锁 thread1.start(); //让main函数主线程休眠40ms Thread.sleep(40); threadTrain.flag = false; //此时flag=false,线程thread2执行synchronized函数,拿到this锁 thread2.start(); } } //此时线程thread1需要线程thread2的this锁,线程thread2需要线程thread1的obj锁,互相要锁,并且互相都不释放,就会产生死锁问题。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算