在java中处理线程并发问题,可以简单的加上synchronized,可以在方法或方法内的代码块添加,那现在的问题是,synchronized是锁住了方法还是代码块还是实例对象?
加在方法上:
class Sync {
public synchronized void test() {
System.out.println("test开始..");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test结束..");
}
}
class MyThread extends Thread {
public void run() {
Sync sync = new Sync();
sync.test();
}
}
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
Thread thread = new MyThread();
thread.start();
}
}
}
运行结果: test开始.. test开始.. test开始.. test结束.. test结束.. test结束
可以看到,上面启了3个线程,每个线程实例化一个Sync并调用其方法,所以这里synchronized没有作用,因为线程都加了各自的同步锁,无互斥。
若把test方法上加上static
,则运行结果如下:
test开始.. test结束.. test开始.. test结束.. test开始.. test结束
因为此时,3个线程的同步锁是Sync类对象而不是类实例。
public static synchronized void test() {
System.out.println("test开始..");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test结束..");
}
注:线程sleep时,并不会释放锁.
接下来,把synchronized加到this上,如下:
public void test() {
synchronized(this) {
System.out.println("test开始..");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test结束..");
}
}
运行结果:test开始.. test开始.. test开始.. test结束.. test结束.. test结束
同样的道理,这里的同步锁是自各的对象实例,3个线程互不影响,没有互斥作用
由此得知,synchronized在方法上锁的是对象实例,在代码块里锁的是括号里的对象。别的线程想要拿到锁,就必须等待当前线程执行完成并释放锁,才能再次给对象加锁,达到线程同步互斥作用。
为了提升线程执行效率,就要最小化同步代码块,最小化锁粒度。
上面使用static
实现了线程互斥,其实也可以用同一个对象来实现线程互斥,如下:
class MyThread extends Thread {
private Sync sync;
public MyThread(Sync sync) {
this.sync = sync;
}
public void run() {
sync.test();
}
}
public class Main {
public static void main(String[] args) {
Sync sync = new Sync();
for (int i = 0; i < 3; i++) {
Thread thread = new MyThread(sync);
thread.start();
}
}
}
运行结果:test开始.. test结束.. test开始.. test结束.. test开始.. test结束
可以看到,线程同步互斥了
更好的做法是,直接锁住这个对象的class对象,与static相同,如下:
class Sync {
public void test() {
synchronized (Sync.class) {
System.out.println("test开始..");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test结束..");
}
}
}
class MyThread extends Thread {
public void run() {
Sync sync = new Sync();
sync.test();
}
}
运行结果:test开始.. test结束.. test开始.. test结束.. test开始.. test结束
可以看到,线程仍然同步互斥
综上,若需要同步锁,尽量最小化同步块。
学习交流,欢迎加群:64691032
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。