[Java]同步锁synchronized

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shichimiyasatone/article/details/85047531

在多线程操作数据时需要考虑使用synchronized关键词修饰属性或方法,同步锁synchronized大致可分为两类:对象锁全局锁。在分析同步锁代码时需要关心两个问题:锁的对象是谁谁持有锁

①对象锁:

当一个线程访问对象object的一个synchronized(this)同步代码块或synchronized修饰的实例方法时,其他线程对该object中所有其它synchronized(this)同步代码块或synchronized修饰的实例方法的访问将被阻塞。

public class Demo {

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

}
class MyRunnable implements Runnable{

	static int i;

	@Override
	public void run() {
		add();
	}

	synchronized void add() {
		System.out.println(Thread.currentThread().getName()+"开始,i = "+i);
		i++;
		System.out.println(Thread.currentThread().getName()+"结束,i = "+i);
	}
}

输出结果:

在上面的例子中,synchronized 修饰实例方法,锁的对象是myRunnable,持有锁的为当前执行该方法的线程。循环创建并启动的三个线程都调用myRunnable对象的同步add()方法,当其中某个线程执行add()方法时需要先获得myRunnable对象的锁,若对象锁被其他线程占用,该线程将阻塞在此,等待锁的获得。

②全局锁

当一个线程访问类的一个synchronized(类名.class)同步代码块或synchronized修饰的类方法时,其他线程对该类中所有其它synchronized(类名.class)同步代码块或synchronized修饰的类方法的访问将被阻塞。

public class Demo {

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

}
class Sync{
	static int i;
	synchronized static void add() {
		System.out.println(Thread.currentThread().getName()+"开始,i = "+i);
		i++;
		System.out.println(Thread.currentThread().getName()+"结束,i = "+i);
	}
}

输出结果:

在上面的例子中,synchronized 修饰类方法,锁的对象是Sync.class,持有锁的为当前执行该方法的线程。循环创建并启动的三个线程都调用Sync类的静态方法add(),当其中某个线程执行add()方法时需要先获得Sync类的锁,若对象锁被其他线程占用,该线程将阻塞在此,等待锁的获得。

总结:

1.使用synchronized对象锁时,线程需要拿到的是该对象的锁,否则将无法操作该对象中所有带有对象锁的属性和方法。

2.使用全局锁时,需要拿到的是类文件的锁,否则将无法操作该类所有带全局锁的属性和方法。

猜你喜欢

转载自blog.csdn.net/shichimiyasatone/article/details/85047531