synchronized 描述
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限, 在Java里边就是拿到某个同步对象的锁(一个对象只有一把锁); 如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池等待队列中)。 取到锁后,他就开始执行同步代码(被synchronized修饰的代码); 线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中等待的某个线程就可以拿到锁执行同步代码了。 这样就保证了同步代码在统一时刻只有一个线程在执行。
多线程的线程同步机制实际上是靠锁的概念来控制的。
对象锁
加锁非静态方法,即是对象锁。synchronized修饰非静态方法、同步代码块的synchronized (this)用法和synchronized (非this对象)的用法锁的是对象,线程想要执行对应同步代码,需要获得对象锁。
看一个例子
定义一个SysTask,加锁一个非静态方法doSomeThing()
package thread.demo;
public class SysTask {
public synchronized void doSomeThing(){
System.out.println("start thread name is :" + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end thread name is :" + Thread.currentThread().getName());
}
}
再创建一个测试类Test
package thread.demo;
public class Test {
public static void main(String[] args) {
SysTask sysTask = new SysTask();
for (int i=0 ;i<3;i++){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
sysTask.doSomeThing();
}
});
thread.setName(i+"-name");
thread.start();
}
}
}
结果:
start thread name is :0-name
end thread name is :0-name
start thread name is :2-name
end thread name is :2-name
start thread name is :1-name
end thread name is :1-name
很明显此处是同步的。因为此处循环里面的是同一个对象,而对象锁是锁住的对象,所以是同步的。
下面修改一下测试类:
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
SysTask sysTask = new SysTask();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
sysTask.doSomeThing();
}
});
thread.setName(i + "-name");
thread.start();
}
}
}
此时结果是:
start thread name is :0-name
start thread name is :1-name
start thread name is :2-name
end thread name is :0-name
end thread name is :1-name
end thread name is :2-name
此时是异步的,因为每次调用同步方法的时候都是实例化不同的对象。
类锁
加锁静态方法,即类锁。可以换个方向理解,静态方法其实就是类方法,所以加锁静态方法,即类锁。类锁的范围是整个实体类,即全局锁。
继续看例子:
package thread.demo;
public class SysTaskStatic {
public synchronized static void doSomeThing(){
System.out.println("start thread name is :" + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end thread name is :" + Thread.currentThread().getName());
}
}
测试类:
package thread.demo;
public class TestSatic {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
SysTaskStatic.doSomeThing();
}
});
thread.setName(i + "-name");
thread.start();
}
}
}
结果是:
start thread name is :0-name
end thread name is :0-name
start thread name is :1-name
end thread name is :1-name
start thread name is :2-name
end thread name is :2-name
结果很明显,是同步的,可以看出来类锁是达到了全局的效果。
网友评论