上一篇列举了多个线程对同一个对象的竞态代码区的synchronized的同步效果和机制,这篇来验证下,多个线程,多个对象synchronized的同步问题
首先明确一点,synchronized的同步机制是建立在对象上的,不同对象是不会有影响的,这也是实际的应用场景吻合。
多线程 多个对象 synchronized
public class ThreadDemo2 {
/**
* 竞态方法 method1
*
* */
public synchronized void method1(){
try{
System.out.println(Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName()+" over");
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 普通方法 method2
*
* */
public void method2(){
System.out.println(Thread.currentThread().getName()+" normal method");
}
/**
* 竞态方法 method3
*
* */
public synchronized void method3(){
try{
System.out.println(Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName()+" over");
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args){
final ThreadDemo2 threadDemo1 = new ThreadDemo2();
final ThreadDemo2 threadDemo2 = new ThreadDemo2();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
threadDemo1.method1();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
threadDemo2.method1();
}
},"t2");
t1.start();
t2.start();
}
}
运行结果:
t1
t2
t2 over
t1 over
可以看出两个线程同时执行了不同对象的竞态方法,如果不同对象在多线程下还想实现同步,那就需要类级别的锁(或者对竞态的区域加static修饰),性能狠狠狠差,相当于无论谁无论在哪调用这个class的对象都需要获得锁权限。我觉得加这种级别的锁的人要么是喝多了,要么是胆子太大。
synchronized 同步或者竞态代码块的粒度要保持好
public class ThreadDemo3 {
/**
* method1
*
* */
public void method1(){
try{
//TODO 这里是公共区域 不具有竞争属性 可以做很多准备工作
System.out.println(Thread.currentThread().getName()+"---out the door");
synchronized(this) {//上锁 关门
//TODO 这里是竞态区域 需要获取锁才能进来 同样是锁的是对象
System.out.println(Thread.currentThread().getName()+"---in the door");
Thread.sleep(5000);
}
System.out.println(Thread.currentThread().getName()+" over");
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args){
final ThreadDemo3 threadDemo1 = new ThreadDemo3();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
threadDemo1.method1();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
threadDemo1.method1();
}
},"t2");
t1.start();
t2.start();
}
}
运行结果
t1---out the door
t1---in the door
t2---out the door
t2---in the door
t1 over
t2 over
从结果可以看出 t1 和 t2 虽然都进入了method1 但是t2要在门外等t1在门里面把事情办完才能进去,与之前的在方法上同步,这个粒度要小一些,可以在公共区域处理进门前的逻辑
synchronized 虽然好用但是也要注意粒度,注意场合!