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
可以看到所有的加锁方法,其实都是共用同一把锁。