Java synchronized 同步锁

java中可以利用锁锁住一些代码块,让同一时间只有一个线程访问共用一把锁的代码块。锁分为类锁和对象锁,类锁是静态的,跟随类,而方法锁是属于实例的。synchronized关键字表示告诉监视器此段代码加锁,其他线程不允许访问,类或者对象都只拥有一把锁,当某个线程正在运行某段加锁代码时,其他任何线程都不能运行类或对象的任何其他加锁代码。

synchronized可以加在方法前:

[static] synchronized method( ) { }

或者这样加在代码块前:

synchronized(object|class){ }

当其修饰静态方法和传入类的代码块时,此锁是类锁,类锁属于类,与任何实例无关:

static synchronized method( ) { }
synchronized(class){ }

当其修饰实例方法和传入对象的代码块时,此锁是对象锁,只影响这个对象:

synchronized method( ) { }
synchronized(object){ }

测试对象锁:

public class MethodSyncTest {
	
	public int dataint = 0;
	public String datastr;
	public boolean databool;
	
	public synchronized void setInt(){
		for (int x = 0; x < 10; x++) {
			dataint = x+1;
			System.out.println("将整数设置为: "+dataint);
		}
	}
	
	public synchronized void setString() {
		for (int x = 0; x < 10; x++) {
			datastr = "字符串" + (x+1);
			System.out.println("将字符串设置为: "+datastr);
		}
	}
	
	public synchronized void setBoolean() {
		for (int x = 0; x < 10; x++) {
			if (databool) {
				databool = false;
			} else {
				databool = true;
			}
			System.out.println("将布尔值设置为: "+databool);
		}
	}

}
MethodSyncTest test = new MethodSyncTest();
		
Thread t1 = new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("当前线程: "+Thread.currentThread().getName());
		test.setInt();
	}
}, "线程1");

Thread t2 =new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("当前线程: "+Thread.currentThread().getName());
		test.setString();
	}
}, "线程2");
		
Thread t3 =new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("当前线程: "+Thread.currentThread().getName());
		test.setBoolean();
	}
}, "线程3");

t1.start();
t2.start();
t3.start();

运行结果:

当前线程: 线程2
当前线程: 线程1
当前线程: 线程3
将字符串设置为: 字符串1
将字符串设置为: 字符串2
将字符串设置为: 字符串3
将字符串设置为: 字符串4
将字符串设置为: 字符串5
将字符串设置为: 字符串6
将字符串设置为: 字符串7
将字符串设置为: 字符串8
将字符串设置为: 字符串9
将字符串设置为: 字符串10
将布尔值设置为: true
将布尔值设置为: false
将布尔值设置为: true
将布尔值设置为: false
将布尔值设置为: true
将布尔值设置为: false
将布尔值设置为: true
将布尔值设置为: false
将布尔值设置为: true
将布尔值设置为: false
将整数设置为: 1
将整数设置为: 2
将整数设置为: 3
将整数设置为: 4
将整数设置为: 5
将整数设置为: 6
将整数设置为: 7
将整数设置为: 8
将整数设置为: 9
将整数设置为: 10

测试类锁:

public class MethodSyncTest {
	
	public static int dataint = 0;
	public static String datastr;
	public static boolean databool;
	
	public static synchronized void setInt(){
		for (int x = 0; x < 10; x++) {
			dataint = x+1;
			System.out.println("将整数设置为: "+dataint);
		}
	}
	
	public static synchronized void setString() {
		for (int x = 0; x < 10; x++) {
			datastr = "字符串" + (x+1);
			System.out.println("将字符串设置为: "+datastr);
		}
	}
	
	public static synchronized void setBoolean() {
		for (int x = 0; x < 10; x++) {
			if (databool) {
				databool = false;
			} else {
				databool = true;
			}
			System.out.println("将布尔值设置为: "+databool);
		}
	}

}
Thread t1 = new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("当前线程: "+Thread.currentThread().getName());
		MethodSyncTest.setInt();
	}
}, "线程1");

Thread t2 =new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("当前线程: "+Thread.currentThread().getName());
		MethodSyncTest.setString();
	}
}, "线程2");

Thread t3 =new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("当前线程: "+Thread.currentThread().getName());
		MethodSyncTest.setBoolean();
	}
}, "线程3");

t1.start();
t2.start();
t3.start();

运行结果:

当前线程: 线程3
当前线程: 线程2
当前线程: 线程1
将整数设置为: 1
将整数设置为: 2
将整数设置为: 3
将整数设置为: 4
将整数设置为: 5
将整数设置为: 6
将整数设置为: 7
将整数设置为: 8
将整数设置为: 9
将整数设置为: 10
将布尔值设置为: true
将布尔值设置为: false
将布尔值设置为: true
将布尔值设置为: false
将布尔值设置为: true
将布尔值设置为: false
将布尔值设置为: true
将布尔值设置为: false
将布尔值设置为: true
将布尔值设置为: false
将字符串设置为: 字符串1
将字符串设置为: 字符串2
将字符串设置为: 字符串3
将字符串设置为: 字符串4
将字符串设置为: 字符串5
将字符串设置为: 字符串6
将字符串设置为: 字符串7
将字符串设置为: 字符串8
将字符串设置为: 字符串9
将字符串设置为: 字符串10

可以看到所有的加锁方法,其实都是共用同一把锁。

发表评论

邮箱地址不会被公开。 必填项已用*标注