synchronized锁住的是代码还是对象

1.synchronized作用

在Java中,synchronized关键字是用来控制线程同步的。在多线程的环境下,控制synchronized代码段不被多个线程同时执行。

2.synchronized用法

synchronized既可以加在一段代码上,也可以加在方法上。

3.对象锁和全局锁区别

  • 对象锁:synchronized(this)以及非static的synchronized方法。锁的是这个对象。
  • 全局锁:synchronized(类名.class)和static 的synchronized方法。锁的是那个写了synchronized关键字的方法或者代码块。(static方法可以直接类名.方法名()调用,无法使用this,所以它锁的不是this,而是类的Class对象)
3.1对象锁
public class Sync {
	public synchronized void testSync(Thread t) {
	    System.out.println(t.getName() + "开始执行...");
	
	    try {
	        Thread.sleep(1000);
	    } catch (InterruptedException e) {
	        e.printStackTrace();
	    }
	
	    System.out.println(t.getName() + "执行完毕...");
	}
}

testSync()方法是一个非static的synchronized方法。锁住的是当前的对象

public class MyThread extends Thread {

    @Override
    public void run() {
        Sync sync = new Sync();
        sync.testSync(this);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            Thread t = new MyThread();
            t.start();
        }
    }
}

使用多线程进行测试。代码创建了3个线程,在run()方法中创建Sync对象并进行调用testSync()方法。在testSync()方法调用前后,都打印了哪个线程名开始执行和执行完毕。这样,就可以清晰地看出每个线程被调用的先后顺序
在这里插入图片描述
从测试结果来看,上面的那3个线程是同时运行Sync中的testSync()方法。感觉关键字synchronized没起到同步的作用。。。

将修饰testSync()方法的关键字synchronized去掉,在方法内部加上synchronized(this)。

public class Sync {

    public void testSync() {
        synchronized (this) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述
结果还是一样:三个线程是同时启动的。

【注意】:synchronized(this)以及非static的synchronized方法只能防止多个线程同时执行同一个对象的同步代码段。

        当synchronized锁住一个对象后,如果别的线程也想拿到这个对象的锁,就必须等待这个线程执行完成并释放锁后,才能再次给对象加锁,这样才达到线程同步的目的。即使两个不同的代码段(两个不同的非静态同步方法),都是锁同一个对象,那么这两个代码段也不能在多线程环境下同时运行

上述代码中,三个线程同时启动的原因???
        每个线程中都new了一个Sync类的对象,也就是产生了三个不同的Sync对象。由于不是同一个对象,所以,可以多线程同时运行synchronized方法或代码段。

为了验证上述的观点,修改一下代码,让三个线程使用同一个Sync对象

public class MyThread extends Thread {

    private Sync sync;

    public MyThread(Sync sync) {
        this.sync = sync;
    }

    @Override
    public void run() {
        sync.testSync(this);
    }

    public static void main(String[] args) {
        Sync sync = new Sync();
        for (int i = 0; i < 3; i++) {
            Thread t = new MyThread(sync);
            t.start();
        }
    }
}

在这里插入图片描述
可见,实现了多线程同步,关键字synchronized起作用了。

3.2全局锁

如果真的想锁住这段代码,要怎么做?也就是,如果还是最开始的那段代码,每个线程new一个Sync对象,怎么才能让testSync()方法不会被多线程执行。

【解决方案】:只要锁住同一个对象就行了(synchronized后的括号中锁同一个固定对象)。但是,比较多的做法是让synchronized锁这个类对应的Class对象。

public class Sync {

    public void testSync(Thread t) {
        synchronized (Sync.class) {
            System.out.println(t.getName() + "开始执行...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(t.getName() + "执行完毕...");
        }
    }
}
public class MyThread extends Thread {

    @Override
    public void run() {
        Sync sync = new Sync();
        sync.testSync(this);
    }

    public static void main(String[] args) {
    
        for (int i = 0; i < 3; i++) {
            Thread t = new MyThread();
            t.start();
        }
    }
}

在这里插入图片描述

转载:https://blog.csdn.net/xiao__gui/article/details/8188833?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值