实现线程同步,让多个线程排队依次获取某个资源,保证数据不会出错。
Synchronized 锁定的是什么元素?
1.修饰方法
1.1修饰静态方法
public class SyncTest {
public static synchronized void func1() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("11111");
}
public static synchronized void func2() {
System.out.println("22222");
}
}
class Main {
public static void main(String[] args) {
SyncTest syncTest = new SyncTest();
SyncTest syncTest2 = new SyncTest();
new Thread(() -> syncTest.func1()).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> syncTest2.func2()).start();
}
}
修饰静态方法锁定的是类。同步
1.2修饰非静态方法(锁定是方法的调用者)
public class SyncTest {
public synchronized void func1() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("11111");
}
public synchronized void func2() {
System.out.println("22222");
}
}
class Main {
public static void main(String[] args) {
SyncTest syncTest = new SyncTest();
new Thread(() -> syncTest.func1()).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> syncTest.func2()).start();
}
}
synchronized修饰方法,锁定调用者。在main方法中syncTest调用func1和func2实现了同步,等待func1执行完再执行func2。
如果使用new一个SyncTest synctest2去调用func2,则func1和func2同时运行。
2.修饰代码块(锁定的是synchronized() 传入的对象)
class Main2 {
public static void main(String[] args) {
Test2 test2 = new Test2();
for (int i = 0; i < 5; i++) {
new Thread(() -> {
Integer num = 1;
test2.func(num);
}).start();
}
}
}
class Test2 {
public void func(Integer num) {
// synchronized (this) { //this 指的是类的对象,对象一样排队,不一样不用排队
// synchronized (Test2.class) { //Test2.class 锁定的是类,都需要排队
synchronized (num) { //num 传入的参数,一样的话排队,不一样不用排队
System.out.println("start...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end...");
}
}
}