Java学习笔记——并发之synchronized

    synchronized是Java关键字,为多线程场景下防止临界资源访问冲突提供支持,当任务要执行别synchronized关键字保护的代码时,它将检查锁是否可用,然后获取锁,执行代码,最后再释放锁。有三种用法:synchronized方法、

synchronized静态方法、synchronized代码块。

1.synchronized方法

 首先看一下没有加synchronized关键字执行下面程序的结果:

public class TreadTest {

	public void method1(){
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("method1");
	}
	
	public void method2() {		
		System.out.println("method2");
	}
	
	public static void main(String[] args) {
		TreadTest test = new TreadTest();
		
		Thread t1 = new Thread(new Runnable() {			
			@Override
			public void run() {
				test.method1();
			}
		});
		
		Thread t2 = new Thread(new Runnable() {			
			@Override
			public void run() {
				test.method2();
			}
		});
		
		t1.start();
		t2.start();
	}

  上面代码中,method1比method2多了1s的延时,因此在t1和t2线程同时执行的情况下,先打印出method2的执行结果:

method2
method1
   当method1和method2加上synchronized关键字后,代码如下:

	public synchronized void method1(){
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("method1");
	}
	
	public synchronized void method2() {		
		System.out.println("method2");
	}
  此时,由于method1占用了锁,因此method2必须要等待method1执行完之后才能执行,因此先打印出method1的执行结果:

method1
method2
  因此 synchronized锁定是当前的对象,当前对象的synchronized方法在同一时间只能执行其中的一个,另外的synchronized方法需挂起等待,但不影响非synchronized方法的执行。下面的synchronized方法和synchronized代码块(把整个方法 synchronized ( this )包围起来)等价的。
	public synchronized void method1(){
		
	}
	
	public  void method2() {		
		synchronized(this){
			
		}
	}

2.synchronized静态方法

   synchronized静态方法是作用在整个类上面的方法,相当于把类的class作为锁,示例代码如下:

public class TreadTest {

	public static synchronized void method1(){
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println("method1");
	}
	
	public static void method2() {		
		synchronized(TreadTest.class){
			System.out.println("method2");
		}
	}
	
	public static void main(String[] args) {		
		Thread t1 = new Thread(new Runnable() {			
			@Override
			public void run() {
				TreadTest.method1();
			}
		});
		
		Thread t2 = new Thread(new Runnable() {			
			@Override
			public void run() {
				TreadTest.method2();
			}
		});
		
		t1.start();
		t2.start();
	}

}
    由于将class作为锁,因此method1和method2存在着竞争关系,method2中synchronized(ThreadTest.class)等同于在method2的声明时void前面直接加上synchronized。上述代码的执行结果仍然是先打印出method1的结果:

method1
method2

3. synchronized代码块

  synchronized代码块应用于处理临界资源的代码块中,不需要访问临界资源的代码可以不用去竞争资源,减少了资源间的竞争,提高代码性能。示例代码如下:

public class TreadTest {

	private Object obj = new Object();
	
	public void method1(){
		System.out.println("method1 start");
		
		synchronized(obj){
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("method1 end");
		}
	}
	
	public void method2() {
		System.out.println("method2 start");
		
		// 延时10ms,让method1线获取到锁obj
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		synchronized(obj){
			System.out.println("method2 end");
		}
	}
	
	public static void main(String[] args) {
		TreadTest test = new TreadTest();
		Thread t1 = new Thread(new Runnable() {			
			@Override
			public void run() {
				test.method1();
			}
		});
		
		Thread t2 = new Thread(new Runnable() {			
			@Override
			public void run() {
				test.method2();
			}
		});
		
		t1.start();
		t2.start();
	}

}
   执行结果如下:
method1 start
method2 start
method1 end
method2 end
上述代码中,执行method2方法,先打印出 method2 start, 之后执行同步块,由于此时obj被method1获取到,method2只能等到method1执行完成后再执行,因此先打印method1 end,然后在打印method2 end。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值