版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34083066/article/details/86798598
synchronized关键字
给对象加锁。当请求进入该方法时或者代码块时,先检查是否有其他线程占用,如果有则等待其执行完释放锁才能获得锁。
修饰对象不同,效果也不同。
当修饰的是普通方法或者普通代码块时,只有是使用同一实例时,才能有锁的效果。当是不同实例的时候,锁无效。
当修饰的是静态方法或者静态代码块时,无论使用的实例是否相同,都会有加锁的效果。因为类初始化时,静态方法和静态代码块都会初始化到类的内存中,所以每个实例使用的都是一个静态方法或者静态代码块。
synchronized类型
对象锁
使用synchronized关键字给普通方法,普通代码块进行加锁。
例如:
import lombok.extern.slf4j.Slf4j;
/**
* 对象锁
* 使用synchronized对象锁进行并发控制
* @author wm
*
*/
@Slf4j
public class SyncDemo2 implements Runnable{
static SyncDemo2 instance = new SyncDemo2();
Object lock1 = new Object();
Object lock2 = new Object();
public static void main(String[] args) throws InterruptedException {
log.info("start");
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
t1.join();
t2.join();
log.info("finish");
}
/**
* 普通方法锁
*/
@Override
public synchronized void run() {
log.info("运行对象锁普通方法锁形式");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("运行结束。");
}
/**
* 运行对象锁代码块形式时使用多把锁
* 观察进入顺序。
* 2019-01-08 14:40:57,887 [INFO] main (SyncDemo2.java:20)- start
* 2019-01-08 14:40:57,891 [INFO] Thread-0 (SyncDemo2.java:36)- 运行对象锁代码块形式,lock1
* 2019-01-08 14:41:00,893 [INFO] Thread-0 (SyncDemo2.java:42)- lock1运行结束。
* 2019-01-08 14:41:00,894 [INFO] Thread-0 (SyncDemo2.java:45)- 运行对象锁代码块形式,lock2
* 2019-01-08 14:41:00,895 [INFO] Thread-1 (SyncDemo2.java:36)- 运行对象锁代码块形式,lock1
* 2019-01-08 14:41:03,895 [INFO] Thread-0 (SyncDemo2.java:51)- lock2运行结束。
* 2019-01-08 14:41:03,896 [INFO] Thread-1 (SyncDemo2.java:42)- lock1运行结束。
* 2019-01-08 14:41:03,897 [INFO] Thread-1 (SyncDemo2.java:45)- 运行对象锁代码块形式,lock2
* 2019-01-08 14:41:06,898 [INFO] Thread-1 (SyncDemo2.java:51)- lock2运行结束。
* 2019-01-08 14:41:06,899 [INFO] main (SyncDemo2.java:27)- finish
*/
// @Override
// public void run() {
// synchronized (lock1) {
// log.info("运行对象锁代码块形式,lock1");
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// log.info("lock1运行结束。");
// }
// synchronized (lock2) {
// log.info("运行对象锁代码块形式,lock2");
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// log.info("lock2运行结束。");
// }
// }
/**
* 运行对象锁代码块形式
*/
// @Override
// public void run() {
// synchronized (this) {
// log.info("运行对象锁代码块形式");
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// log.info("运行结束。");
// }
// }
/**
* 没进行任何锁保护
* 执行时,会同时进行,同时结束。
*/
// @Override
// public void run() {
// log.info("对象锁代码块形式");
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// log.info("运行结束。");
// }
}
类锁
给静态方法或者静态代码块进行加锁。
例如:
扫描二维码关注公众号,回复:
5426848 查看本文章
import lombok.extern.slf4j.Slf4j;
/**
* 类锁
* 使用synchronized类锁进行并发控制
* 注意区分main中和对象锁的不同
* 两个想成使用的是两个不同的实例,如果是对象锁,就无法达到控制并发的效果了
* 但是如果使用类锁还可以达到这样的效果
* @author wm
*
*/
@Slf4j
public class SyncDemo3 implements Runnable{
static SyncDemo3 instance1 = new SyncDemo3();
static SyncDemo3 instance2 = new SyncDemo3();
Object lock1 = new Object();
Object lock2 = new Object();
public static void main(String[] args) throws InterruptedException {
log.info("start");
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
t1.join();
t2.join();
log.info("finish");
}
@Override
public void run() {
method();
}
/**
* 类锁的静态方法形式
*/
private static synchronized void method() {
log.info("运行类锁形态方法形式");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("运行结束。");
}
/**
* 运行类锁代码块形式
*/
// @Override
// public void run() {
// synchronized (SyncDemo3.class) {
// log.info("运行类锁代码块形式");
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// log.info("运行结束。");
// }
// }
}