Java多线程安全问题和锁

news/2024/10/23 9:24:15/

多线程安全问题和锁

文章目录

    • 多线程安全问题和锁
    • 线程在jvm中的特点
    • 锁的出现
    • synchronized 关键字-监视器锁monitor lock
    • 死锁的产生和避免

什么是线程安全问题?
当多个线程同时操作同一个数据时,可能会出现数据不一样的情况,这就是线程安全问题。
线程安全机制用于保证多个线程访问数据时的一致性.
线程安全问题体现在三个方面:
1、原子性
2、可见性
3、有序性

原子操作是不可分割的,体现在两个方面: 一个线程对数据的操作对于其他的线程来说是原子的,要么操作完成,要么什么也没做;当一个线程在操作数据时,不允许其他的线程参与.

可见性是指线程对共享数据的访问是否对其他的线程可见. A线程对共享数据做了修改, B线程不一定能够立即读取到A线程修改后的数据。

有序性包含指令重排序与内存重排序指令重排序是指CPU执行指令的顺序与程序的顺序可能不一样; 内存重排序是指内存访问顺序与感知顺序可能不一样。

线程在jvm中的特点

在这里插入图片描述

1)每个线程都有独立的线程栈
2)一个线程栈不能访问另外一个线程栈的内容
3)所有的线程栈都可以访问堆中对象
4)局部变星理解为存储在方法栈中,局部变量肯定不存在线程安全问题
5)当多个线程同时访问同一个对象的实例变量,或者访问同一 个静态变量时才可能会出现线程安全问题
6)线程安全问题不是肯定会发生的,有时可能会出现线程安全问题

java抽象内存模型
在这里插入图片描述
1)每个线程都有自己独立的工作内存
2)线程1无法访问线程2的工作内存
3)线程在访问共享数据时,会把主内存中的共享变量复制到自己的工作内存中,线程操作的是工作内存中数据的副本

锁的出现

多线程并发操作同一个数据可能会引发线程安全问题。
多个线程串行操作某个数据就不会引发线程安全问题。

锁就是把多个线程对数据的并发操作转换为串行操作。

想要访问共享数据,必须先获得锁对象(锁就相当于一个访问许可证)。锁对象在某一时刻只能被一个线程持有,锁具有排它性。当线程访问完共享数据后,会自动释放锁对象。

在这里插入图片描述
1)某个线程想要访问共享数据,必须先获得锁对象
2)锁对象在某一时刻只能被一个线程持有当线程2获得了锁对象之后,如果还有其他线程想要访问共享数据,其他的线程也必须先获得锁对象现在锁对象被线程2持有其他的线程转为阻塞状态
3)当线程2执行完临界区代码后,会释放锁对象阻塞队列中的线程会获得锁对象,访问共享数据
4)注意: 多个线程想要实现同步访问,必须使用同一一个锁对象读数据时也需要进行同步,否则会出现脏读现象(另一个线程操作的中间值,还未更新)

synchronized 关键字-监视器锁monitor lock

synchronized的底层是使用操作系统的mutex lock实现的。

synchronized 关键字的使用
1、同步代码块
1)可以定义一个常量作为锁对象
2)只要是同一个锁对象,同步代码快可以在不同的方法体中也能同步
2、同步实例方法
直接使用synchronized修饰实例方法
把整个方法体作为同步代码块,默认的锁对象就是this对象
3、同步静态方法
就是使用synchronized修饰静态方法
把整个方法体作为同步代码块,默认的锁对象是 当前类的运行时类对象,简单的理解为把当前类的字节码文件作为锁

当线程释放锁时,JMM会把该线程对应的工作内存中的共享变量刷新到主内存中
当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内 存中读取共享变量
synchronized用的锁是存在Java对象里的

在这里插入图片描述
锁的是SynchronizedDemo 对象

/*
锁的是SynchronizedDemo 对象*/
public class SynchronizedDemo {public synchronized void methond() {}public static void main(String[] args) {SynchronizedDemo demo = new SynchronizedDemo();demo.methond(); // 进入方法会锁 demo 指向对象中的锁;出方法会释放 demo 指向的对象中的锁}
}

锁的 SynchronizedDemo 类的对象

/*
锁的是SynchronizedDemo 类的对象*/
public class SynchronizedDemo {public synchronized static void methond() {}public static void main(String[] args) {// 进入方法会锁 SynchronizedDemo.class 指向对象中的锁;// 出方法会释放 SynchronizedDemo.class 指向的对象中的锁methond();}
}

谁调用的这个方法锁的就是哪个对象

/*
谁调用的这个方法锁的就是哪个对象*/
public class SynchronizedDemo {public void methond() {// 进入代码块会锁 this 指向对象中的锁;// 出代码块会释放 this 指向的对象中的锁         synchronized (this) {}}public static void main(String[] args) {SynchronizedDemo demo = new SynchronizedDemo();demo.methond();}
}

死锁的产生和避免

当多个线程需要使用多个同步锁时,如果获得锁的顺序不一致,可能会导致相互等待的情况,这种现象称为死锁。

如何解决死锁问题?。
如果需要获得多个锁对象时,保证获得锁对象的顺序一致,就可以避免死锁的产生。


http://www.ppmy.cn/news/195084.html

相关文章

记一次RC级别下MySQL死锁问题

背景 在工作中碰到一次死锁问题,业务背景是在mq接收商品主数据时会更新商品其他数据,由于商品主数据和商品其他信息是一对多的关系,所以采用先删后增的方式,结果异常监管平台报出来死锁警告。 这是商品其他信息表,数…

<Java>多线程——Lock锁方式解决线程安全问题

Lock接口提供了与synchronized关键字类似的同步功能 synchronized 方法或语句的使用提供了对与每个对象相关的隐式监视器锁定的访问,但却强制所有锁定获取和释放均要出现在一个块结构中:当获取了多个锁定时,它们必须以相反的顺序释放&#x…

北京城里有900万辆自行车

There are nine million bicycles in Beijing 北京城里有900万辆自行车Thats a fact 这是个事实Its a thing we cant deny 是我们无法否认的事Like the fact that I will love you till I die 就像我会爱你直到死去 We are twelve billion light years from the edge 我们…

倍受歧视的北京骑车人

倍受歧视的北京骑车人 标签:杂谈 天冷的时候我每天都在坐公交车上下班,加上很多时间都在车上打盹,对于骑车没有很深的感觉,但是天气转暖后,实在难以忍受热的要死的车厢和在因为道路拥堵 车里漫长的等待,并且…

共享单车公司每年花上亿元赎车

来源|36氪Pro 编辑|杨林 杨轩 当王萧风尘仆仆赶到现场时,发现一辆大型厢货正停在路中央,一些陌生人正在把他的单车不停往上运——这是共享单车行业折腾到第六年,出现的一个新群体:第三方“扣车公司”。王萧…

小蜜单车 免费骑车 BUG

前段时间 杭州出现了 很多的小蜜单车. 电动的 骑起来非常的方便. 有一天偶然发现一个BUG,竟然可以免费骑车. 骑了不少次,算是受了不少恩惠了, 写个软文分享下,算是报答了. 当然我8月1号上报BUG了, 客服表示这是不可能的, 不会把我当傻子了吧,仁至义尽了,分享下BUG给各位吧,让各…

隔壁王大爷都弄明白了“锁“——java锁机制(实现原理)

终于明白了JavaAPI里面的锁 锁的出现: 第一次接触到锁的概念是在java多线程遇见的锁,再写多线程用到了synchronized和lock两种锁,采用锁是为了保证线程的安全,每个线程都存在自己私有和共有的数据区,私有的数据区只对内…

【Java多线程】你了解死锁吗?【Lock锁】

➤ Java多线程编程【一文全解】 文章目录 01 什么是死锁?02 如何避免死锁?03 Lock 锁 01 什么是死锁? 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放…