1 介绍
可以修饰一下四种类型
- 修饰代码块
- 修饰方法
- 修饰静态方法
- 修饰类
本质上修饰的只有两种 - 实例化的对象
- 类
2 用法
2.1 修饰代码块
synchronized 这里修饰的是代码快,实际修饰的是Object这个对象的实例lock(给lcok这个对象实例加锁)。
两个代码块运行都需要lock这个对象,所以保证了同步
public static void main(String[] args) throws InterruptedException {
// 创建锁对象 lock
Object lock = new Object();
Thread thread1 = new Thread(() -> {
// synchronized修饰下面代码,执行下面代码需要获取lock对象,并且不让其他人获取lock对象
synchronized (lock) {
for (int i = 0; i < 5000; i++) {
count++;
}
}
});
Thread thread2 = new Thread(() -> {
// synchronized修饰下面代码,执行下面代码需要获取lock对象,并且不让其他人获取lock对象
synchronized (lock) {
for (int i = 0; i < 5000; i++) {
count--;
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
2.2 修饰方法
修饰非静态方法,锁的是这个方法的对象(实例)
public class Demo {
static int count = 0;
public static void main(String[] args) throws InterruptedException {
SyncDemo demo = new SyncDemo();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
demo.add();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
demo.add();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
}
public class SyncDemo {
public synchronized void add(){
Demo.count++;
}
}
2.3 修饰静态方法
这里synchronized修饰的是静态方法add(),那就是给这个静态方法所属的类加锁
运行这个方法需要获取当前类,也就是当前类的class对象
static int count = 0;
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
add();
});
Thread thread2 = new Thread(() -> {
add();
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
/**
* synchronized修饰方法,表示该方法被使用时会上锁,不能被其他线程调用
*/
public synchronized static void add() {
for (int i = 0; i < 5000; i++) {
count++;
}
}
2.4 修饰类
static int count = 0;
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
synchronized (SyncDemo.class) {
for (int i = 0; i < 5000; i++) {
count ++;
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (SyncDemo.class) {
for (int i = 0; i < 5000; i++) {
count --;
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
3 线程八锁
3.1
synchronized 修饰成员方法,修饰对象实例
结果12 或者21
@Slf4j
public class Demo {
public static void main(String[] args) throws InterruptedException {
Number number = new Number();
new Thread(() -> {
log.info("begin...");
number.a();
}).start();
new Thread(() -> {
log.info("begin...");
number.b();
}).start();
}
}
@Slf4j
class Number {
public synchronized void a() {
log.info("1");
}
public synchronized void b() {
log.info("2");
}
}
3.2
synchronized 修饰成员方法,修饰对象实例
结果 1 1秒后 2 | 2 1秒后 1
@Slf4j
public class Demo {
public static void main(String[] args) throws InterruptedException {
Number number = new Number();
new Thread(() -> {
log.info("begin...");
number.a();
}).start();
new Thread(() -> {
log.info("begin...");
number.b();
}).start();
}
}
@Slf4j
class Number {
public synchronized void a() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
log.info("1");
}
public synchronized void b() {
log.info("2");
}
}
3.3
这里多了一个c方法,但是没有被synchronized 修饰
所以c方法的运行和 a b方法没有关系
a b互斥 c随意
c的运行一定在a前
@Slf4j
public class Demo {
public static void main(String[] args) throws InterruptedException {
Number number = new Number();
new Thread(() -> {
log.info("begin...");
number.a();
}).start();
new Thread(() -> {
log.info("begin...");
number.b();
}).start();
new Thread(() -> {
log.info("begin...");
number.c();
}).start();
}
}
@Slf4j
class Number {
public synchronized void a() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
log.info("1");
}
public synchronized void b() {
log.info("2");
}
public void c() {
log.info("2");
}
}
3.4
锁的不是同一个对象实例,所以a b没有关系
@Slf4j
public class Demo {
public static void main(String[] args) throws InterruptedException {
Number number1 = new Number();
Number number2 = new Number();
new Thread(() -> {
log.info("begin...");
number1.a();
}).start();
new Thread(() -> {
log.info("begin...");
number2.b();
}).start();
}
}
@Slf4j
class Number {
public synchronized void a() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
log.info("1");
}
public synchronized void b() {
log.info("2");
}
}
3.5
a锁的是类,b锁的是对象实例,二者没有关系
@Slf4j
public class Demo {
public static void main(String[] args) throws InterruptedException {
Number number1 = new Number();
Number number2 = new Number();
new Thread(() -> {
log.info("begin...");
try {
Number.a();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
log.info("begin...");
number2.b();
}).start();
}
}
@Slf4j
class Number {
public static synchronized void a() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
log.info("1");
}
public synchronized void b() {
log.info("2");
}
}
3.6
a b锁的都是类,互斥
@Slf4j
public class Demo {
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
log.info("begin...");
try {
Number.a();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
log.info("begin...");
Number.b();
}).start();
}
}
@Slf4j
class Number {
public static synchronized void a() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
log.info("1");
}
public static synchronized void b() {
log.info("2");
}
}
3.7
a 锁的是类 b 锁对象实例 二者没有关系
@Slf4j
public class Demo {
public static void main(String[] args) throws InterruptedException {
Number number1 = new Number();
Number number2 = new Number();
new Thread(() -> {
log.info("begin...");
try {
number1.a();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
log.info("begin...");
number2.b();
}).start();
}
}
@Slf4j
class Number {
public static synchronized void a() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
log.info("1");
}
public synchronized void b() {
log.info("2");
}
}
3.8
a锁类 b锁类 二者互斥
@Slf4j
public class Demo {
public static void main(String[] args) throws InterruptedException {
Number number1 = new Number();
Number number2 = new Number();
new Thread(() -> {
log.info("begin...");
try {
number1.a();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
log.info("begin...");
number2.b();
}).start();
}
}
@Slf4j
class Number {
public static synchronized void a() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
log.info("1");
}
public static synchronized void b() {
log.info("2");
}
}