1 前言

  • 非静态方法的同步锁是当前对象(this)(对象锁)
  • 静态方法的同步锁是当前类的字节码(类锁)
  • 不同的锁之间能并发

2 同一对象内

本节主类与资源类如下:

class Resorce{ //资源
	static int x=0;
	static int y=0;
}

public class Main {
	public static void main(String[] args) {
		Operate op=new Operate();
		Thread t1=new Thread() {
			public void run() {
				op.fun1();
			}
		};
		Thread t2=new Thread() {
			public void run() {
				op.fun2();
			}
		};
		t1.start();
		t2.start();
	}
}

2.1 两个非static方法,一个被synchronized修饰,一个未被修饰,能否并发?(能并发)

(本例中两个方法访问同一资源,能并发;若访问不同资源,也能并发)

class Operate{
	void fun1() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t1-uux:"+Resorce.x);
		}
	}
	
	synchronized void fun2() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t2-sux:"+Resorce.x);
		}
	}
}

运行结果:

t1-sux:2
t2-uux:2
t2-uux:4
t1-sux:3
t1-sux:6
t2-uux:5

sux:被synchronized修饰,未被static修饰,资源为x;

uux:未被synchronized修饰,未被static修饰,资源为x。

2.2 两个非static方法,都被synchronized修饰,能否并发?(不能并发)

(本例中两个方法访问不同资源,不能并发;若访问同一资源,也不能并发)

class Operate{
	synchronized void fun1() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t1-sux:"+Resorce.x);
		}
	}
	
	synchronized void fun2() {
		for(int i=0;i<3;i++) {
			Resorce.y++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t2-suy:"+Resorce.y);
		}
	}
}

运行结果:

t1-sux:1
t1-sux:2
t1-sux:3
t2-suy:1
t2-suy:2
t2-suy:3

sux:被synchronized修饰,未被static修饰,资源为x;

suy:被synchronized修饰,未被static修饰,资源为y。

2.3 两个synchronized方法,一个被static修饰,一个未被修饰,能否并发?(能并发)

(本例中两个方法访问同一资源,能并发;若访问不同资源,也能并发)

class Operate{
	synchronized void fun1() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t1-sux:"+Resorce.x);
		}
	}
	
	synchronized static void fun2() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t2-ssx:"+Resorce.x);
		}
	}
}

运行结果:

t1-ssx:2
t1-ssx:3
t2-sux:2
t1-ssx:4
t2-sux:5
t2-sux:6

ssx:被synchronized修饰,被static修饰,资源为x;

sux:被synchronized修饰,未被static修饰,资源为x。

2.4 两个static方法,都被synchronized修饰,能否并发?(不能并发)

(本例中两个方法访问不同资源,不能并发;若访问同一资源,也不能并发)

class Operate{
	synchronized static void fun1() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t1-ssx:"+Resorce.x);
		}
	}
	
	synchronized static void fun2() {
		for(int i=0;i<3;i++) {
			Resorce.y++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t2-ssy:"+Resorce.y);
		}
	}
}

运行结果:

t1-ssx:1
t1-ssx:2
t1-ssx:3
t2-ssy:1
t2-ssy:2
t2-ssy:3

ssx:被synchronized修饰,被static修饰,资源为x;

ssy:被synchronized修饰,被static修饰,资源为y。

3 不同对象间

针对第2节中的两种不能并发的情况进行讨论,主类和资源类如下:

class Resorce{ //临界资源
	static int x=0;
	static int y=0;
}

public class Main {
	public static void main(String[] args) {
		Operate op1=new Operate();
		Operate op2=new Operate();
		Thread t1=new Thread() {
			public void run() {
				op1.fun1();
			}
		};
		Thread t2=new Thread() {
			public void run() {
				op2.fun2();
			}
		};
		t1.start();
		t2.start();
	}
}

3.1 两个非static方法,都被synchronized修饰,能否并发?(能并发)

(本例中两个方法访问同一资源,能并发;若访问不同资源,也能并发)

class Operate{
	synchronized void fun1() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t1-sux:"+Resorce.x);
		}
	}

	synchronized void fun2() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t2-sux:"+Resorce.x);
		}
	}
}

运行结果:

t2-sux:2
t1-sux:2
t1-sux:4
t1-sux:5
t2-sux:3
t2-sux:6

sux:被synchronized修饰,未被static修饰,资源为x。

3.2 两个static方法,都被synchronized修饰,能否并发?(不能并发)

(本例中两个方法访问不同资源,不能并发;若访问同一资源,也不能并发)

class Operate{
	synchronized static void fun1() {
		for(int i=0;i<3;i++) {
			Resorce.x++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t1-ssx:"+Resorce.x);
		}
	}
	
	synchronized static void fun2() {
		for(int i=0;i<3;i++) {
			Resorce.y++;
			for(int j=0;j<1000;j++); //延时
			System.out.println("t2-ssy:"+Resorce.y);
		}
	}
}

运行结果:

t1-ssx:1
t1-ssx:2
t1-ssx:3
t2-ssy:1
t2-ssy:2
t2-ssy:3

ssx:被synchronized修饰,被static修饰,资源为x;

ssy:被synchronized修饰,被static修饰,资源为y。

4 注意事项

这里的资源不是临界资源,临界资源由信号量来控制其访问。

​ 声明:本文转自使用synchronized对并发性的影响