使用 synchronized 修饰静态方法和非静态方法有什么区别

本文深入解析Java中的synchronized关键字,阐述其如何实现线程同步,包括对象锁与静态同步的区别,以及多线程环境下对同一对象及不同对象实例的访问控制。

synchronized的说明

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

synchronized与static synchronized区别

说明

synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”,类的两个不同实例就没有这种约束了。

那么static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码块。

实际上,如果在类中某方法或某代码块中有 synchronized,那么在生成一个该类实例后,该类也就有一个监视块,监视线程并发访问改实例synchronized保护块。而static synchronized则是该类的所有实例公用一个监视块,这便是两个的区别了。

也就是synchronized相当于 this.synchronized,而static synchronized相当于Something.synchronized.

写个类:

public class SynTest implements Runnable{

    @Override
    public void run(){
        System.out.println("haha");
    }
    public synchronized static void method(){
        System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
                + System.currentTimeMillis()+ "进入printA");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程名称为:" + Thread.currentThread().getName()
                 + "在" + System.currentTimeMillis() + "离开printA");
    }

    public synchronized  void method2(){
        System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
                + System.currentTimeMillis()+ "进入printB");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程名称为:" + Thread.currentThread().getName()
                + "在" + System.currentTimeMillis() + "离开printB");
    }
}

测试方法:

 public static void main(String[] args) {
        SynTest synTest =new SynTest();
        SynTest synTest2 =new SynTest();
        Thread thread =new Thread(new Runnable() {
            @Override
            public void run() {
                synTest.method();
            }
        });
        Thread thread3 =new Thread(new Runnable() {
            @Override
            public void run() {
                synTest2.method();
            }
        });
        Thread thread2 =new Thread(new Runnable() {
            @Override
            public void run() {
                synTest.method2();
            }
        });
        Thread thread4 =new Thread(new Runnable() {
            @Override
            public void run() {
                synTest2.method2();
            }
        });
        thread.start();
        thread2.start();
        //thread3.start();
        //thread4.start();
    }

结果:

同一对象实例下多线程访问method()和method2()是互不影响的

不同对象实例下多线程是不能同时访问method()的,因为synchronized static method(),所有实例公用一个监视块

所以结果为:

但是不同对象实例下多线程是可以同时访问method2()的

结果为:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值