线程安全

什么是线程安全

某个代码在单线程或者是多线程运行时没有出现bug就叫做线程安全

因为我们线程之间的调度是无序的也是随机调度的(抢占式执行)

 

当我们执行这两个线程时,希望输出的是10000000,但是我们这里的线程是存在线程安全问题的,因为这两个线程是并发执行的,count++是随机调度的,

 

什么是锁synchronized()

为了避免线程安全问题,通过锁竞争让第二线程的指令无法插入到第一个线程的指令,从而达到线程安全

 

锁的写法

 1.可以在线程内加锁使用synchronized,在创建一个实例对象作为锁,确保在进行并发执行时只有一个线程可以执行count++,其他线程只能等待当前线程释放锁后才能进入同步块,由于synchronized的存在两个线程不会被同时修改

 

 

2.创建一个类和方法,在这个方法里面加锁,而这个锁里面的this就是当前对象,就是Test这个类,而我们后面调用的t.add也是在调用Test这个对象,所以就不会出现线程安全问题

 

3.把锁的参数写成类的对象

 

4.修饰普通方法,相当于给this加锁

 

synchronized是可重入的锁

当我们的代码中写成了重复嵌套锁的情况下,在第一次是成功上锁,在第二次加锁时就会判断当前线程是否为持有锁的线程,如果不是同一个线程就会进行阻塞,如果是同一个线程就不会再次进行上锁,锁内部有个计数器,只会在这个计数器进行++操作

在释放锁的时候也是一样的,会先释放里面的锁,让计数机--,真正释放锁是最外面的那一层

 
 
内存可见性引起的线程安全问题
在预期通过t2线程输入的整数使t1结束,实际上输入flag的值的时候t1线程并不会结束,t1线程一直在进行循环,每次得到的结果都是相同的,分析出t1线程的访问寄存器的速度远远超过访问内存的速度,所以jvm自动优化我们的代码,就不在重复去读内存了,而是直接去访问寄存器中的缓存,从而大幅度的提高循环的执行速度
就是t2修改了内存,而t1没有看到这个内存的变化就叫做内存可见性安全问题

当我们把代码进行调整,jvm的优化方式就会根据代码变化进行优化,但是它什么时候触发优化,什么时候不触发优化都是不确定的

 

java中也提供了volatile可以强制关闭jvm的优化功能,但是相对应的执行速度和在内存中的开销就回变大,好处就是数据的准确性和逻辑性提高了

 

 

 

wait

让当前的代码主动放弃进入cpu调度(释放锁),进入阻塞等待,让后面的代码有机会拿到锁

notify

唤醒wait等待的线程重新加入到锁竞争

 wait和notify都必须放在锁里面,且他们的对象必须是同一个,如果有多个线程有wait对象都是一样的情况下,notify是随机唤醒其中一个

 

posted @ 2025-02-19 16:44  油头男孩  阅读(34)  评论(0)    收藏  举报