Synchronize使用静态变量作为对象锁

前言:
有人觉得使用静态变量作为对象锁,用的是类锁,还有人觉得静态变量在使用的过程中,里面的值改变,对象的地址会改变,所以用的就不是通一把锁,今天我们验证下。
一、使用同一把静态变量锁的情况:

public class SynchronizeTest {
    public static List<Person>list1;
    static {
        list1 = new ArrayList<>();
    }
    public static void method1(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (list1) {
                    for (int i = 0; i < 20; i++) {
                        System.out.println("method1");
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
    public static void method2(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (list1) {
                    for (int i = 0; i < 20; i++) {
                        System.out.println("method2");
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
    public static void main(String[] args) {
        SynchronizeTest t1 = new SynchronizeTest();
        SynchronizeTest t2 = new SynchronizeTest();
        t1.method1();
        t2.method2();
    }

结果:
运行完method1后再运行method2;因此使用的是同一把锁,但只要使用静态变量就是类锁吗?不是的,结果看实验二。

二、使用不同的静态变量锁的情况:

public class SynchronizeTest {
    public static List<Person>list1;
    public static List<Person>list2;
    static {
        list1 = new ArrayList<>();
        list2 = new ArrayList<>();
    }
    public static void method1(){

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (list1) {
                    for (int i = 0; i < 20; i++) {
                        System.out.println("method1");
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
    public static void method2(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (list2) {
                    for (int i = 0; i < 20; i++) {
                        System.out.println("method2");
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        }).start();
    }
    public static void main(String[] args) {
        SynchronizeTest t1 = new SynchronizeTest();
        SynchronizeTest t2 = new SynchronizeTest();
        t1.method1();
        t2.method2();
    }
}

结果:method1和method2交替运行。因此,使用静态变量作为锁,用的不是类锁。
在这里插入图片描述三、对静态变量值的改变,对锁是否有影响。

我在对method1和method2这两个方法使用list1这个锁的过程中,开辟了第三个线程对list1的值的改变,发现list1这个锁的不受影响,依然是method1执行完毕后再执行method2。

public class SynchronizeTest {

    public static Person person;
    public static List<Person>list1;
    static {
        list1 = new ArrayList<>();
        person = new Person(0);
    }
    public static void method1(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (list1) {
                    for (int i = 0; i < 20; i++) {
                        System.out.println("method1");
                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        }).start();
    }
    public static void method2(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (list1) {
                    for (int i = 0; i < 20; i++) {
                        System.out.println("method2");
                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
    public static void method3(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=0;i<20;i++){
                    try {
                        Thread.sleep(20);
                        System.out.println("-----");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Person p = new Person(i);
                    list1.add(person);
                }
            }
        }).start();
    }
    public static void main(String[] args) {
        SynchronizeTest t1 = new SynchronizeTest();
        SynchronizeTest t2 = new SynchronizeTest();
        SynchronizeTest t3 = new SynchronizeTest();
        t1.method1();
        t2.method2();
        t3.method3();
    }
}

最后总结
使用list1和list2后使用的分别是list1和list2的对象锁,虽然是静态变量,但使用的不是类锁。
使用静态变量,对静态变量值的改变,不会影响到此变量的地址,用的依然是同一把锁。

`synchronized` 是 Java 中用于实现线程同步的关键字。它可以用于修饰方法或代码块,以确保在同一时间只有一个线程可以访问被修饰的代码区域。 当一个方法或代码块被 `synchronized` 修饰时,它被称为同步方法或同步代码块。在同步方法或同步代码块中,只有获取到锁的线程才能执行其中的代码,其他线程需要等待锁释放后才能进入。 `synchronized` 的作用是保护共享资源,防止多个线程同时修改或访问导致数据不一致的问题。它提供了互斥访问的机制,使得在同一时间只能有一个线程修改共享资源,确保了线程安全性。 在 Java 中,有三种使用 `synchronized` 的方式: 1. 同步实例方法:使用 `synchronized` 修饰实例方法,锁定当前对象实例。只有一个线程可以同时执行该实例方法。 ```java public synchronized void synchronizedMethod() { // 同步代码块 } ``` 2. 同步静态方法:使用 `synchronized` 修饰静态方法,锁定当前类的 Class 对象。只有一个线程可以同时执行该静态方法。 ```java public static synchronized void synchronizedStaticMethod() { // 同步代码块 } ``` 3. 同步代码块:使用 `synchronized` 关键字修饰代码块,指定锁对象。只有获取到锁对象的线程才能执行该代码块。 ```java public void synchronizedBlock() { synchronized (lockObject) { // 同步代码块 } } ``` 需要注意的是,`synchronized` 只提供了基本的线程同步机制,使用时要注意避免死锁和性能问题。在某些情况下,可以使用更高级的并发工具类,如 `java.util.concurrent` 包下的锁、条件变量等来实现更灵活和高效的线程同步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值