Synchronized作用、用法、性质、原理、缺陷
Synchronized作用:
能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。
Synchronized两个用法:
1、对象锁:
包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)。
同步代码块形式:
public class SynchronizedObjectCodeBlock implements Runnable {
static SynchronizedObjectCodeBlock instance = new SynchronizedObjectCodeBlock();
Object lock1 = new Object();
Object lock2 = new Object();
@Override
public void run() {
synchronized (lock1) {
System.out.println("lock1,我叫:" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " lock1运行结束。");
}
synchronized (lock2) {
System.out.println("lock2,我叫:" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " lock2运行结束。");
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
System.out.println("finished");
}
}
方法锁形式(synchronized 修饰普通方法,不能是静态方法):
public class SynchronizedObjectMethod implements Runnable{
static SynchronizedObjectMethod instance = new SynchronizedObjectMethod();
@Override
public void run() {
method();
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
System.out.println("finished");
}
public synchronized void method(){
System.out.println("我的对象锁的方法修饰符形式,我叫:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "运行结束。");
}
}
2、类锁:
指Synchronized修饰静态的方法或指定锁为Class对象。
静态方法:
public class SynchronizedClassStatic implements Runnable{
static SynchronizedClassStatic instance1 = new SynchronizedClassStatic();
static SynchronizedClassStatic instance2 = new SynchronizedClassStatic();
@Override
public void run() {
method();
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
System.out.println("finished");
}
public static synchronized void method(){
System.out.println("我是类锁的第一种形式:static形式,我叫:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "运行结束。");
}
}
Class对象:
public class SynchronizedClassClass implements Runnable {
static SynchronizedClassClass instance1 = new SynchronizedClassClass();
static SynchronizedClassClass instance2 = new SynchronizedClassClass();
@Override
public void run() {
method();
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
System.out.println("finished");
}
public void method() {
synchronized (SynchronizedClassClass.class) {
System.out.println("我是类锁的第二种形式:class形式,我叫:" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "运行结束。");
}
}
}
Synchronized性质
1、可重入
(粒度scope,可理解为范围)
可重入通俗解释:
在北京和上海给车子上牌,需要给车子摇号,摇到号相当于线程获取到了锁,但是家里有3辆车都想上牌,摇到一次号只能上一个车,摇到一次车牌就想上三辆车是不可以的,称为不可重入;如果摇号是可重入的,摇到一个号就可以一直获取车牌,直到自己不愿意获取,则称为可重入。
一个线程拿到一个锁,就可以一直用,为可重入;一个线程拿到一个锁,用了一次需要先释放再和其他线程竞争,为不可重入。
2、不可中断
PS:LOCK类可以拥有中断的能力
Synchronized原理
1、加锁和释放锁的原理
public class SynchronizedToLock { Lock lock = new ReentrantLock(); //第一个方法和第二个方法是等价的,第二个方法相当于解剖第一个方法 public synchronized void method1() { System.out.println("我是synchronized形式的锁"); } public void method2() { lock.lock(); try { System.out.println("我是lock形式的锁"); } finally { lock.unlock(); } } public static void main(String[] args) { SynchronizedToLock s = new SynchronizedToLock(); s.method1(); s.method2(); } }
2、可重入原理
3、可见性原理
JMM为java内存模型的缩写
Synchronized修饰的代码块或方法,在执行完毕后,被锁住的对象所做的任何修改,都需要在释放锁之前从线程内存写回到主内存中。
Synchronized缺陷