并发编程:锁对象同步代码块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程:锁对象同步代码块相关的知识,希望对你有一定的参考价值。


1、同步代码块

使用synchronized声明的方法在某些情况下是有弊端的,比如A线程调用同步的方法执行一个很长时间的任务,那么B线程就必须等待比较长的时间才能执行,这样的情况下可以使用synchronized代码块去优化代码执行时间,也就是通常所说的减小锁的粒度。

代码

public class Demo7 {
	public void doLongTimeTask(){
		try {
			
			System.out.println("当前线程开始:" + Thread.currentThread().getName() + 
					", 正在执行一个较长时间的业务操作,其内容不需要同步");
			Thread.sleep(2000);
			
			synchronized(this){
				System.out.println("当前线程:" + Thread.currentThread().getName() + 
					", 执行同步代码块,对其同步变量进行操作");
				Thread.sleep(1000);
			}
			System.out.println("当前线程结束:" + Thread.currentThread().getName() +
					", 执行完毕");
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		final Demo7 demo7 = new Demo7();
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				demo7.doLongTimeTask();
			}
		},"t1");
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				demo7.doLongTimeTask();
			}
		},"t2");
		t1.start();
		t2.start();
	}
}

效果:

    技术分享

2、synchronized可以使用任意的Object进行加锁

public class ObjectLock {

	public void method1(){
		synchronized (this) {	// 对象锁
			try {
				System.out.println("do method1..");
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void method2(){		// 类锁
		synchronized (ObjectLock.class) {
			try {
				System.out.println("do method2..");
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	private Object lock = new Object();
	public void method3(){		// 任何对象锁
		synchronized (lock) {
			try {
				System.out.println("do method3..");
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		
		final ObjectLock objLock = new ObjectLock();
		new Thread(new Runnable() {
			@Override
			public void run() {
				objLock.method1();
			}
		}, "t1").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				objLock.method2();
			}
		}, "t2").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				objLock.method3();
			}
		}, "t3").start();
	}
}

效果:

    技术分享

说明:这里结果同时打印的。


另外特别注意,就是不要使用String的常量加锁,会出现死循环问题

3、锁对象的改变问题

当使用一个对象进行加锁的时候,要注意对象本身发生改变的时候,那么持有的锁就不同。如果对象本身不发生改变,那么依然是同步的,即使是对象的属性值发生了改变。

注意:同一对象属性的修改不会影响锁的情况

本文出自 “我爱大金子” 博客,请务必保留此出处http://1754966750.blog.51cto.com/7455444/1905609

以上是关于并发编程:锁对象同步代码块的主要内容,如果未能解决你的问题,请参考以下文章

转:Java并发编程之一:可重入内置锁

Java多线程编程对象及变量的并发访问

JUC并发编程 -- 避免临界区的竞态条件之synchronized 解决方案(同步代码块)

JAVA的高并发编程

Java并发编程

并发编程__Lock 同步锁