你会用java中synchronized吗?--锁定非静态实例
1、synchronized使用于一个语句块,锁定一个非静态对象的实例,是实例级别的锁,同一个对象在这个语句块一次只能由一个线程执行。
Talk is cheap.Show me the code.
Code:
package chapter2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* Created by MyWorld on 2016/3/14.
*/
public class SynchronizedDemo {
public static void main(String[] args) {
Business business = new Business();
Worker worker = new Worker(business);
Thread threadFirst = new Thread(worker, "First");
Thread threadSecond = new Thread(worker, "Second");
threadFirst.start();
threadSecond.start();
}
}
class Worker implements Runnable {
private Business business;
public Worker(Business business) {
this.business = business;
}
@Override
public void run() {
try {
business.doBusiness();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Business {
private static Logger logger = LoggerFactory.getLogger(Business.class); public void doBusiness() throws InterruptedException {
synchronized (this) {
logger.info("enter synchronized monitor");
TimeUnit.SECONDS.sleep(10);
logger.info("leave synchronized monitor");
}
}
}



2、执行上面的代码,看看两个线程是否并发执行锁定的语句块了。
从打印上看,是串行的。因为是实例级别的锁吗?
有人问,synchronized(this)中的this是什么东东啊?
就是Business这个对象的实例了。
Output:
2016-03-15 07:07:13,154 [First] INFO - enter synchronized monitor
2016-03-15 07:07:23,156 [First] INFO - leave synchronized monitor
2016-03-15 07:07:23,156 [Second] INFO - enter synchronized monitor
2016-03-15 07:07:33,156 [Second] INFO - leave synchronized monitor

3、说的也对。能不能不用this,换个更容易看懂的实例行不?
好的。
Code:
class Business {
private static Logger logger = LoggerFactory.getLogger(Business.class); private final byte[] lock = new byte[0];
public void doBusiness() throws InterruptedException {
synchronized (lock) {
logger.info("enter synchronized monitor");
TimeUnit.SECONDS.sleep(10);
logger.info("leave synchronized monitor");
}
}
}

4、执行更改后的代码。看看执行结果有没有发生变化。
没有的。因为this和lock在虚拟机看来是一样的,都是一个实例嘛。
Output:
2016-03-15 07:07:13,154 [First] INFO - enter synchronized monitor
2016-03-15 07:07:23,156 [First] INFO - leave synchronized monitor
2016-03-15 07:07:23,156 [Second] INFO - enter synchronized monitor
2016-03-15 07:07:33,156 [Second] INFO - leave synchronized monitor

5、你说的都对。能不能创建两个Worker对象再试一下,每个Worker都是线程对象嘛?!
上Code:
Business business = new Business();
Worker workerFirst = new Worker(business);
Worker workerSecond = new Worker(business);
Thread threadFirst = new Thread(workerFirst, "First");
Thread threadSecond = new Thread(workerSecond, "Second");
threadFirst.start();
threadSecond.start();

6、执行最新的代码。看看打印的日志,线程有没有串行执行。
是的,是串行的。。
Output:
2016-03-15 07:21:28,760 [First] INFO - enter synchronized monitor
2016-03-15 07:21:38,762 [First] INFO - leave synchronized monitor
2016-03-15 07:21:38,762 [Second] INFO - enter synchronized monitor
2016-03-15 07:21:48,764 [Second] INFO - leave synchronized monitor

7、不对啊。
synchronized在修饰非静态方法时,你有一个例子不是可以并行执行的,不都是实例级别的锁么?
是的,这个tx是真用心学了。
现在把代码改造一下,让两个线程并行执行同步代码块中的内容。
既然是实例对象级别的锁,创建两个Business实例,线程执行时不就并行了。
因为锁是在不同对象中的,相当于每个线程分别使用用自己独特的一把锁,两个线程各自锁定,互想没有什么关系。
这样不就可以串行执行了
Code:
Business businessFirst = new Business();
Business businessSecond = new Business();
Worker workerFirst = new Worker(businessFirst);
Worker workerSecond = new Worker(businessSecond);
Thread threadFirst = new Thread(workerFirst, "First");
Thread threadSecond = new Thread(workerSecond, "Second");
threadFirst.start();
threadSecond.start();

8、执行上面最新的代码。
执行中。。。。
看到了吧,两个线程是同时打印了“enter synchronized monitor”
是不是已经并行执行synchronized中语句了。
Output:
2016-03-15 07:28:58,510 [First] INFO - enter synchronized monitor
2016-03-15 07:28:58,510 [Second] INFO - enter synchronized monitor
2016-03-15 07:29:08,511 [First] INFO - leave synchronized monitor
2016-03-15 07:29:08,511 [Second] INFO - leave synchronized monitor
