synchronize简介
一、单个对象的同步。每个方法可以同步到不同的对象,对象之间是相互独立的。
private Object synObject1 = new Object();
private Object synObject2 = new Object();
}
public void f1() {
synchronized (synObject1) {
//TODO
}
}
public void f2() {
synchronized (synObject2) {
//TODO
}
}
f1与f2分别同步到不同的对象上,只要获得相应同步对象的对象锁,线程就可以运行。
二、同步到当前类实例对象上。当某一个方法同步到当前的类实例对象上时,线程只有获得当前类实例的对象锁才可以继续运行。同步到当前类实例对象上有两种方法:
1、同步对象设为this。
public void f3() {
synchronized (this) {
//TODO
}
}
2、在方法上使用synchronize关键字。
public synchronized void f4() {
// TODO
}
三、同步到当前类实例上。当使用一个静态对象作为同步对象时,线程只有获得当前类实例时,才可以继续运行,也就是所谓的类锁。也可以直接获取当前类实例来作为同步对象,有两种方法:
1、使用xxx.class
public class Test {
public void f6() {
synchronized (Test.class) {
// TODO
}
}
}
2、使用Class.forName(XXXX);
public class Test {
public void f7() throws ClassNotFoundException {
synchronized (Class.forName("com.example.Test")) {
// TODO
}
}
}
3.静态方法
public class Test {
public synchronized void f7() {
}
}
所谓的“线程八锁”
其实就是考察 synchronized 锁住的是哪个对象
情况1:12 或 21
@Slf4j(topic = "c.Number")
class Number{
public synchronized void a() {
log.debug("1");
}
public synchronized void b() {
log.debug("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
情况2:1s后12,或 2 1s后 1
@Slf4j(topic = "c.Number")
class Number{
public synchronized void a() {
sleep(1);
log.debug("1");
}
public synchronized void b() {
log.debug("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
以上两个测试,可以看出synchronized修饰的方法,同一时刻,只能有一个线程进入
情况3:3 1s 12 或 23 1s 1 或 32 1s 1
class Number{
public synchronized void a() {
sleep(1);
log.debug("1");
}
public synchronized void b() {
log.debug("2");
}
public void c() {
log.debug("3");
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
new Thread(()->{ n1.c(); }).start();
}
c方法没有被synchronized修饰,所以c方法肯定会被执行,a,b方法被synchronized修饰,同一时刻只能执行其中一个。
情况4:2 1s 后 1
@Slf4j(topic = "c.Number")
class Number{
public synchronized void a() {
sleep(1);
log.debug("1");
}
public synchronized void b() {
log.debug("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
synchronized加在方法上锁的是当前对象,n1与n2不是同一个对象,此时synchronized是不生效的
情况5:2 1s 后 1
class Number{
public static synchronized void a() {
sleep(1);
log.debug("1");
}
public synchronized void b() {
log.debug("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
synchronized加在静态方法上锁的是Number.class,synchronized加在方法上锁的是当前对象。两者锁的不是同一个东西。相当于synchronized失效了,所以最后的输出结果为2 1s 后 1
情况6:1s 后12, 或 2 1s后 1
class Number{
public static synchronized void a() {
sleep(1);
log.debug("1");
}
public static synchronized void b() {
log.debug("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
synchronized加在静态方法上锁的是Number.class,同一时间只能有一个线程调用a方法或b方法
情况7:2 1s 后 1
class Number{
public static synchronized void a() {
sleep(1);
log.debug("1");
}
public synchronized void b() {
log.debug("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
synchronized加在静态方法上锁的是Number.class,synchronized加在方法上锁的是当前对象。两者锁的不是同一个东西。相当于synchronized失效了,所以最后的输出结果为2 1s 后 1
情况8:1s 后12, 或 2 1s后 1
class Number{
public static synchronized void a() {
sleep(1);
log.debug("1");
}
public static synchronized void b() {
log.debug("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
synchronized加在静态方法上锁的是Number.class,同一时间只能有一个线程调用a方法或b方法,所以输出结果为:1s 后12 或 2 1s后 1