synchronized
synchronized:同步,在时间上一致,同速进行
1、为什么要使用synchronized?
在并发编程中存在线程安全问题,多线程共享数据,synchronized可以保证在同一时刻只有一个线程读取或者执行某个代码块或者对象,即synchronized修饰的内容。
2、synchronized的实现方式?
(1)普通同步方法,锁是当前的实例对象,进入同步代码前要获得当前实例的锁。
(2)静态同步方法,锁是当前类的class对象,进入同步代码前要获得当前类的对象锁。
(3)同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。
3、举一个例子
package test;
public class volatiletest {
public static void main (String []args){
volatiletest vo = new volatiletest();
vo.UI();
}
private threadtest th = new threadtest();
Thread t1 = new Thread(th);
Thread t2 = new Thread(th);
public void UI(){
t1.start();
t2.start();
}
}
public class threadtest extends Thread{
volatiletest vo;
static int count;
public void increse(){
count++;
}
public void run(){
for(int i=0;i<10000;i++){
increse();
}
System.out.println(count);
}
}
我们创建了两个线程,run()方法中执行increse()方法10000次,每次让count+1,两个线程都读取count当前的值,同一时刻不能保证只有一个线程读取count,导致结果在10000~20000之间,而加了synchronized锁之后,得到了正确的结果20000
public class threadtest extends Thread{
volatiletest vo;
static int count;
public synchronized void increse(){
count++;
}
public void run(){
for(int i=0;i<10000;i++){
increse();
}
System.out.println(count);
}
}
这是没加锁之前的结果,每次执行都不一样。


这是加了锁之后的结果:

synchronized的底层实现:
4、 Java虚拟机对同步锁synchronized的优化:
锁的状态一共有四种,无状态锁、偏向锁、轻量级锁、重量级锁。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁,但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级,
偏向锁:如果一个线程获得了锁,那么锁就进入偏向模式,
轻量级锁:
重量级锁:
5、synchronized锁升级原理
在锁对象的对象头里面,有一个threadid的字段,在第一次访问的时候,threadid为空,jvm让其拥有偏向锁,并将threadid设置为线程id,再次进入的时候判断此id与threadid是否一致,如果不一致,则升级偏向锁为轻量级锁,通过自选循环一定的次数来获取锁的对象,如果仍然未获得,则将轻量级锁升级成重量级锁,中间的过程就是所得升级。
6、synchronized与Lock的区别
(1)synchronized是内置关键字,在jvm层面,Lock是Java的一个类
(2)synchronized自动释放锁,Lock需要手动释放锁,unlock()
(3)用synchronized修饰两个线程,一个线程获得锁后执行,另一个线程等待。如果线程1发生阻塞,则线程2永远等待下去。而Lock则不会一直等下去,获得锁尝试失败后,会自动结束。
(4)synchronized的锁可重入、不可中断、非公平。而Lock是不可重入、可中断、公平。

浙公网安备 33010602011771号