Synchronized是一个同步关键字,在某些多线程场景下,如果不进行同步会导致数据不安全,而Synchronized关键字就是用于代码同步。什么情况下会数据不安全呢,要满足两个条件:一是数据共享(临界资源),二是多线程同时访问并改变该数据。
修饰静态方法,对当前类的Class对象加锁,也就是SyncDemo.class对象
public class SynDemo {
static int value = 0;
public synchronized static void testStaticSync() {
value++;
}
}
修饰实例方法,对当前实例对象this加锁
public class SynDemo {
int i = 0;
int x = 0;
public synchronized void testSync() {
i++;
x++;
}
}
修饰代码块(锁指定对象/类)
synchronized(object) 表示进入同步代码库前要获得 给定对象的锁。
synchronized(类.class) 表示进入同步代码前要获得 给定 Class 的锁
(1)定义一个TestThread类,继承自Thread
(2)TestThread的内部持有一个SycDemo对象
(3)TestThread的run方法内部调用SyncDemo对象的testSync方法执行synchronized修饰的同步方法。
public class SynDemo {
int i = 0;
int x = 0;
// 争抢对象SyncDemo的锁
public synchronized void testSync() {
i++;
x++;
}
static class TestThread extends Thread {
SynDemo lock;
TestThread(SynDemo lock) {
this.lock = lock;
}
@Override
public void run() {
lock.testSync();
}
}
public static void main(String[] args) {
// 锁对象lock1
SynDemo lock1 = new SynDemo();
// 锁对象lock2
SynDemo lock2 = new SynDemo();
TestThread threadA = new TestThread(lock1);
TestThread threadB = new TestThread(lock2);
threadA.start();
threadB.start();
}
}
像这种方式,threadA和threadB是达不到互斥的目的的,因为threadA锁住的是lock1对象;然而thread锁住的是lock2对象。完全争抢的不是同一个锁。

那如果要使得threadA和threadB达到同步的目的,应该怎么做?
需要threadA和threadB争抢同一把锁,争抢同一个同一个对象的锁才可以,也就是像下面那样,也就是threadA和threadB都使用同一对象锁ock1,这样才是正确的:
public static void main(String[] args) {
// 只有一个锁对象lock1
SynDemo lock1 = new SynDemo();
// 两个线程对同一个对象锁进行争抢
TestThread threadA = new TestThread(lock1);
TestThread threadB = new TestThread(lock1);
threadA.start();
threadB.start();
}

对于synchronized修饰static的方法,synchronized锁的是这个类对象,由于类对象只有一个,所以不同线程同时通过类调用这个方法的时候就能互斥的效果。
synchronized 同步语句块的实现使用的是 monitorenter 和 monitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。
JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。
synchronized是可重入锁,内部锁对象中会有一个计数器记录线程获取几次锁,在执行完同步代码块时,计数器的数量会-1,知道计数器的数量为0,就释放这个锁。
一个线程获得锁后,另一个线程想要获得锁,必须处于阻塞或等待状态,如果第一个线程不释放锁,第二个线程会一直阻塞或等待,不可被中断。
无锁-》偏向锁-》轻量级锁-》重量级锁
锁可以升级不可以降级,但是偏向锁状态可以被重置为无锁状态。

1.减少sychronized的范围,同步代码块尽量短,减少同步代码块的执行时间,减少锁竞争。
2.降低sychronized锁的颗粒度(HashTable锁定方法 和 ConcurrentHashMap局部锁定,锁定桶)

3.读写分离(读取不加锁,增加删除的时候加锁)
ConcurrentHashMap,CopyOnWriteArrayList,CopyOnWriteSet
文章出处:https://www.bilibili.com/video/BV1aJ411V763?p=29&vd_source=b901ef0e9ed712b24882863596eab0ca
参考链接:https://blog.csdn.net/tongdanping/article/details/79647337
如何使用:https://blog.csdn.net/chenzengnian123/article/details/122683126