Synchronized的使用

Synchronized的使用

1.为什么使用Synchronized

因为在并发编程中,多线程并发操作共享数据会出现数据安全问题。使用
Synchronized 可以保证同一时刻,只有一个线程能够访问同一个对象的方法。

2.Synchronized的应用方式

1)给普通方法加锁,是锁住的当前对象
2)给代码块加锁,锁住的是给定的对象
3)给静态方法加锁,锁的是当前类型的类对象,简称类锁

3.代码示例

应用1)和2)的代码

public class Test_01 {
	private int count = 0;
	private Object o = new Object();
	
	public void testSync1(){
		synchronized(o){
			System.out.println(Thread.currentThread().getName() 
					+ " count = " + count++);
		}
	}
	
	public  void testSync2(){
		synchronized(this){
			System.out.println(Thread.currentThread().getName()
					+ " count = " + count++);
			try {
				TimeUnit.SECONDS.sleep(3);
				System.out.println("3s后"+Thread.currentThread().getName());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public synchronized void testSync3(){
		System.out.println(Thread.currentThread().getName() 
				+ " count = " + count++);
		try {
			TimeUnit.SECONDS.sleep(3);
			System.out.println("3s后"+Thread.currentThread().getName());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		final Test_01 t = new Test_01();
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.testSync2();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.testSync3();
			}
		}).start();
	}
	
}

在这里插入图片描述
结果分析:
synchronized(this)和synchronized方法都是锁当前对象。
1.当两个并发线程访问同一个对象object中的这个synchronized(this)同步方法时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个方法以后才能执行该方法,但是可以访问非同步方法。保证了方法访问的互斥和变量可见性
2.不同对象锁不相互影响。对于上述testSync1,锁住的是对象o。testSync1和testSync2是不同对象的同步方法,可以同时执行。
3.两个线程访问同一对象的不同synchronized方法,互斥。

应用3)的代码

private static int staticCount = 0;
	public static synchronized void testSync4(){
		System.out.println(Thread.currentThread().getName() 
				+ " staticCount = " + staticCount++);
		try {
			TimeUnit.SECONDS.sleep(3);
			System.out.println("3s后"+Thread.currentThread().getName());

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void testSync5(){
		synchronized(Test_02.class){
			System.out.println(Thread.currentThread().getName() 
					+ " staticCount = " + staticCount++);
		}
	}
	public static void main(String[] args) {
		final Test_02 t = new Test_02();
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.testSync4();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				t.testSync5();
			}
		}).start();
	}

分析结果:
在这里插入图片描述
两个线程实例化两个不同的对象,但是访问的方法是静态的,两个线程发生了互斥。同步静态方法是类对象锁。testSync5锁的也是类对象。
其他情况,比如两个线程访问同步静态方法和非同步方法,是不互斥的。

4.可重入锁

可重复可递归调用的锁。同一个线程,递归调用同步代码,锁定的是同一个锁对象,可重入。
代码举例:

	synchronized void m1(){ // 锁this
		System.out.println("m1 start");
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		m2();
		System.out.println("m1 end");
	}
	synchronized void m2(){ // 锁this
		System.out.println("m2 start");
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("m2 end");
	}
	
	public static void main(String[] args) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				new Test_06().m1();
			}
		}).start();
	}

执行结果:
m1 start
m2 start
m2 end
m1 end

m1()中正常调用m2(),可重入。

synchronized 是一种悲观锁,每次执行临界区代码都会产生冲突,当前线程获得锁后,其他线程只能阻塞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值