Advertisement

Java 类锁和静态锁

阅读量:

Java的锁分为两种:

对象锁 (又称实例锁,synchronized):该锁针对的是该实例对象(当前对象)。
synchronized是对类的当前实例(当前对象) 进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块 ,注意这里是“类的当前实例”, 类的两个不同实例就没有这种约束了。
每个对象都有一个锁,且是唯一的

类锁 (又称全局锁,static synchronized):该锁针对的是类,无论实例 出多少个对象 ,那么线程依然共享该锁。
static synchronized是限制多线程中该类的所有实例同时访问该类所对应的代码块 。(实例.fun实际上相当于class.fun

下面来进行几种情况的测试:一下都是用来测试锁的范围

1、两个静态方法都加锁

复制代码
 package test2;

    
  
    
 public class Test2 {
    
 	public synchronized void add(){
    
 		System.out.println("1 :) ");
    
 		t();
    
 	}
    
 	public void add1(){
    
 		System.out.println("2 :( ");
    
 		t();
    
 	}
    
 	public void t(){
    
 		try {
    
 			Thread.sleep(5000);
    
 		} catch (InterruptedException e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 	}
    
 }

2、两个非静态方法都加锁

复制代码
 package test2;

    
  
    
 public class Test1 extends Thread{
    
 	private int flag;
    
 	
    
 	private Test2 t;
    
 	
    
 	public Test1(int f , Test2 t2){
    
 		flag = f;
    
 		t = t2;
    
 	}
    
 	
    
 	public void run(){
    
 		if(flag == 1)
    
 			try {
    
 //				Test2.add();
    
 				t.add();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 		if(flag == 2)
    
 			try {
    
 				t.add1();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 	}
    
 	public static void main(String[] args) throws InterruptedException {
    
 		Test2 t = new Test2();
    
 		Test1 t1 = new Test1(1,t);
    
 		Test1 t2 = new Test1(2,t);
    
 		t1.start();
    
 		t2.start();
    
 	}
    
 }
    
  
    
 class Test2 {
    
 	public synchronized  void add(){
    
 		System.out.println("1 :) "+System.currentTimeMillis());
    
 		try {
    
 			Thread.sleep(3000);
    
 		} catch (InterruptedException e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 	}
    
 	public synchronized void add1(){
    
 		System.out.println("2 :( "+System.currentTimeMillis());
    
 	}
    
 	
    
 }

结果:此时会锁住加锁的另外一个对象

3、非静态方法、静态方法都加锁

复制代码
 package test2;

    
  
    
 public class Test1 extends Thread{
    
 	private int flag;
    
 	
    
 	private Test2 t;
    
 	
    
 	public Test1(int f , Test2 t2){
    
 		flag = f;
    
 		t = t2;
    
 	}
    
 	
    
 	public void run(){
    
 		if(flag == 1)
    
 			try {
    
 				Test2.add();
    
 //				t.add();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 		if(flag == 2)
    
 			try {
    
 				t.add1();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 	}
    
 	public static void main(String[] args) throws InterruptedException {
    
 		Test2 t = new Test2();
    
 		Test1 t1 = new Test1(1,t);
    
 		Test1 t2 = new Test1(2,t);
    
 		t1.start();
    
 		t2.start();
    
 	}
    
 }
    
  
    
 class Test2 {
    
 	public synchronized static void add(){
    
 		System.out.println("1 :) "+System.currentTimeMillis());
    
 		try {
    
 			Thread.sleep(3000);
    
 		} catch (InterruptedException e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 	}
    
 	public synchronized void add1(){
    
 		System.out.println("2 :( "+System.currentTimeMillis());
    
 	}
    
 	
    
 }

结果:静态带锁的对象锁不住不带锁的非静态方法

4、静态方法加锁、非静态方法不加锁

复制代码
 package test2;

    
  
    
 public class Test1 extends Thread{
    
 	private int flag;
    
 	
    
 	private Test2 t;
    
 	
    
 	public Test1(int f , Test2 t2){
    
 		flag = f;
    
 		t = t2;
    
 	}
    
 	
    
 	public void run(){
    
 		if(flag == 1)
    
 			try {
    
 				Test2.add();
    
 //				t.add();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 		if(flag == 2)
    
 			try {
    
 				t.add1();
    
 //				Test2.add1();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 	}
    
 	public static void main(String[] args) throws InterruptedException {
    
 		Test2 t = new Test2();
    
 		Test1 t1 = new Test1(1,t);
    
 		Test1 t2 = new Test1(2,t);
    
 		t1.start();
    
 		t2.start();
    
 	}
    
 }
    
  
    
 class Test2 {
    
 	public synchronized static void add(){
    
 		System.out.println("1 :) "+System.currentTimeMillis());
    
 		try {
    
 			Thread.sleep(3000);
    
 		} catch (InterruptedException e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 	}
    
 	public void add1(){
    
 		System.out.println("2 :( "+System.currentTimeMillis());
    
 	}
    
 	
    
 }

结果:静态方法加锁,锁不住非静态方法

5、非静态方法加锁、静态方法不加锁

复制代码
 package test2;

    
  
    
 public class Test1 extends Thread{
    
 	private int flag;
    
 	
    
 	private Test2 t;
    
 	
    
 	public Test1(int f , Test2 t2){
    
 		flag = f;
    
 		t = t2;
    
 	}
    
 	
    
 	public void run(){
    
 		if(flag == 1)
    
 			try {
    
 				Test2.add();
    
 //				t.add();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 		if(flag == 2)
    
 			try {
    
 				t.add1();
    
 //				Test2.add1();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 	}
    
 	public static void main(String[] args) throws InterruptedException {
    
 		Test2 t = new Test2();
    
 		Test1 t1 = new Test1(1,t);
    
 		Test1 t2 = new Test1(2,t);
    
 		t1.start();
    
 		t2.start();
    
 	}
    
 }
    
  
    
 class Test2 {
    
 	public static void add(){
    
 		System.out.println("1 :) "+System.currentTimeMillis());
    
 		try {
    
 			Thread.sleep(3000);
    
 		} catch (InterruptedException e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 	}
    
 	public synchronized void add1(){
    
 		System.out.println("2 :( "+System.currentTimeMillis());
    
 	}
    
 	
    
 }

结果:还是锁不住!!!

6、两个静态方法,一个加锁一个不加锁

复制代码
 package test2;

    
  
    
 public class Test1 extends Thread{
    
 	private int flag;
    
 	
    
 	private Test2 t;
    
 	
    
 	public Test1(int f , Test2 t2){
    
 		flag = f;
    
 		t = t2;
    
 	}
    
 	
    
 	public void run(){
    
 		if(flag == 1)
    
 			try {
    
 				Test2.add();
    
 //				t.add();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 		if(flag == 2)
    
 			try {
    
 //				t.add1();
    
 				Test2.add1();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 	}
    
 	public static void main(String[] args) throws InterruptedException {
    
 		Test2 t = new Test2();
    
 		Test1 t1 = new Test1(1,t);
    
 		Test1 t2 = new Test1(2,t);
    
 		t1.start();
    
 		t2.start();
    
 	}
    
 }
    
  
    
 class Test2 {
    
 	public synchronized static void add(){
    
 		System.out.println("1 :) "+System.currentTimeMillis());
    
 		try {
    
 			Thread.sleep(3000);
    
 		} catch (InterruptedException e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 	}
    
 	public static void add1(){
    
 		System.out.println("2 :( "+System.currentTimeMillis());
    
 	}
    
 	
    
 }

结果:静态方法加锁,锁不住不加锁的静态方法

7、两个非静态方法,一个加锁一个不加锁

复制代码
 package test2;

    
  
    
 public class Test1 extends Thread{
    
 	private int flag;
    
 	
    
 	private Test2 t;
    
 	
    
 	public Test1(int f , Test2 t2){
    
 		flag = f;
    
 		t = t2;
    
 	}
    
 	
    
 	public void run(){
    
 		if(flag == 1)
    
 			try {
    
 //				Test2.add();
    
 				t.add();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 		if(flag == 2)
    
 			try {
    
 				t.add1();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 	}
    
 	public static void main(String[] args) throws InterruptedException {
    
 		Test2 t = new Test2();
    
 		Test1 t1 = new Test1(1,t);
    
 		Test1 t2 = new Test1(2,t);
    
 		t1.start();
    
 		t2.start();
    
 	}
    
 }
    
  
    
 class Test2 {
    
 	private int i = 0;
    
 	public synchronized  void add(){
    
 		System.out.println("1 :) "+System.currentTimeMillis());
    
 	}
    
 	public void add1(){
    
 		System.out.println("2 :( "+System.currentTimeMillis());
    
 	}
    
 	
    
 }

执行结果:可以看到,加锁后的非静态方法,锁不住不加锁的静态方法

8、两个非静态方法,一个加锁,一个不加锁,调用相同的方法

复制代码
 package test2;

    
  
    
 public class Test1 extends Thread{
    
 	private int flag;
    
 	
    
 	private Test2 t;
    
 	
    
 	public Test1(int f , Test2 t2){
    
 		flag = f;
    
 		t = t2;
    
 	}
    
 	
    
 	public void run(){
    
 		if(flag == 1)
    
 			try {
    
 //				Test2.add();
    
 				t.add();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 		if(flag == 2)
    
 			try {
    
 				t.add1();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 	}
    
 	public static void main(String[] args) {
    
 		Test2 t = new Test2();
    
 		Test1 t1 = new Test1(1,t);
    
 		Test1 t2 = new Test1(2,t);
    
 		t1.start();
    
 		t2.start();
    
 	}
    
 }
    
  
    
 class Test2 {
    
 	public synchronized  void add(){
    
 		System.out.println("1 :) "+System.currentTimeMillis());
    
 		t();
    
 	}
    
 	public void add1(){
    
 		System.out.println("2 :( "+System.currentTimeMillis());
    
 		t();
    
 	}
    
 	public void t(){
    
 		try {
    
 			Thread.sleep(5000);
    
 		} catch (InterruptedException e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 	}
    
 }

结果:并不会在add方法里锁住t()方法

9、两个非静态方法,一个加锁,一个不加锁,调用相同的方法对同一个变量进行操作

复制代码
 package test2;

    
  
    
 public class Test1 extends Thread{
    
 	private int flag;
    
 	
    
 	private Test2 t;
    
 	
    
 	public Test1(int f , Test2 t2){
    
 		flag = f;
    
 		t = t2;
    
 	}
    
 	
    
 	public void run(){
    
 		if(flag == 1)
    
 			try {
    
 //				Test2.add();
    
 				t.add();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 		if(flag == 2)
    
 			try {
    
 				t.add1();
    
 			} catch (Exception e) {
    
 				// TODO Auto-generated catch block
    
 				e.printStackTrace();
    
 			}
    
 	}
    
 	public static void main(String[] args) throws InterruptedException {
    
 		Test2 t = new Test2();
    
 		for(int i = 0 ; i < 1000 ; i++){
    
 			Test1 t1 = new Test1(1,t);
    
 			Test1 t2 = new Test1(2,t);
    
 			t1.start();
    
 			t2.start();
    
 		}
    
 		Thread.sleep(30);
    
 		System.out.println(t.getI());
    
 	}
    
 }
    
  
    
 class Test2 {
    
 	private int i = 0;
    
 	public synchronized  void add(){
    
 //		System.out.println("1 :) "+System.currentTimeMillis());
    
 		t();
    
 	}
    
 	public void add1(){
    
 //		System.out.println("2 :( "+System.currentTimeMillis());
    
 		t();
    
 	}
    
 	public void t(){
    
 		try {
    
 			i++;
    
 //			Thread.sleep(5000);
    
 		} catch (Exception e) {
    
 			// TODO Auto-generated catch block
    
 			e.printStackTrace();
    
 		}
    
 	}
    
 	public int getI() {
    
 		return i;
    
 	}
    
 	public void setI(int i) {
    
 		this.i = i;
    
 	}
    
 	
    
 }

结果:一个方法加锁也不会保证其调用方法的操作变量的安全性

总结:不管是什么锁,都只能锁住相同类型(静态-静态,非静态-非静态)的带锁的对象。

全部评论 (0)

还没有任何评论哟~