Java中可以使用synchronized进行同步处理 ,难点就是使用synchronized关键字加锁时,锁的到底是哪些东西,本文将进行说明。
synchronized的使用场景:
修饰方法(同步方法)
修饰代码块(同步代码块)
接下来看代码实现:
public class Test{
public static void main(String[] args) {
final TestSynchronzed ts = new TestSynchronzed();
Thread thread1 = new Thread(new Runnable() {
public void run() {
ts.method1(); //thread1调用method1()方法
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
ts.method2(); //Thread2调用method2()方法
}
});
thread1.start();
thread2.start();
}
}
class TestSynchronzed {
public void method1() {
synchronized (this) {
int i = 4;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "," + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void method2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "," + i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出结果:
从method1中synchronized(this)可以看出锁的是当前对象,而method2锁的也是当前对象。所以在上面代码中method1和method2锁的是同一个对象。所以当有一个线程进入method1执行的时候,其他线程被阻塞(既不能访问method1也不能访问method2),只有当对象锁被Thread-0释放后,Thread-1才能访问method2()方法。
如果去掉method2()的synchronized关键字,结果如下:
可以看出这时是交替执行的,原因是当某个线程得到了对象锁,但另一个线程仍然可以访问没有进行同步的代码或方法。上锁了的方法和普通没上锁的方法是互不影响的。 当某个线程获取到对象锁时,只能阻止其他线程获取同一个锁,并不能阻止其他线程访问没有加锁的方法。
上面提到的锁住的是对象,下面将谈到类锁:
public class Test{
public static void main(String[] args) {
final TestSynchronzed ts = new TestSynchronzed();
Thread thread1 = new Thread(new Runnable() {
public void run() {
ts.method1();
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
ts.method2();
}
});
thread1.start();
thread2.start();
}
}
class TestSynchronzed {
public void method1() {
synchronized (TestSynchronzed.class) {
int i = 4;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "," + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static synchronized void method2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "," + i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
上面代码中method1锁的是该类的Class对象。众所周知类的Class对象是描述各个类的组成,一个类有且只有一个Class对象。锁住Class对象相当于锁住了该类的类对象。而method2方法是静态方法,锁住静态方法也相当于锁的是该类的类对象。所以程序运行时各个线程是有序的。
上面提到了类锁和对象锁,需要说明的是类锁和对象锁并不是同一类锁,验证如下:
public class Test{
public static void main(String[] args) {
final TestSynchronzed ts = new TestSynchronzed();
Thread thread1 = new Thread(new Runnable() {
public void run() {
ts.method1();
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
ts.method2();
}
});
thread1.start();
thread2.start();
}
}
class TestSynchronzed {
public void method1() {
synchronized (TestSynchronzed.class) {
int i = 4;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "," + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void method2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + "," + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
可见线程是交替的,说明类锁和对象锁并不是一类锁。