在java中,一般通过同步机制,来解决线程的安全问题
-
方式一:同步代码块
- synchronized(同步监视器){
需要被同步的代码
} - 说明:操作共享数据的代码,即为需要同步的代码
- 共享数据:多个线程共同操作的变量。如:ticket就是共享数据
- 同步监视器,俗称:锁。任何一个类的对象都可以充当锁
- 要求:多个线程必须要共用一把锁
public class WindowTest1 { public static void main(String[] args) { Window1 w1 = new Window1(); Thread thread = new Thread(w1); Thread thread1 = new Thread(w1); Thread thread2 = new Thread(w1); thread.start(); thread1.start(); thread2.start(); } } class Window1 implements Runnable { private int ticket = 100; @Override public void run() { while (true) { synchronized (this) { if (ticket > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ";" + ticket--); } else { break; } } } } }
public class WindowTest2 extends Thread { public static int ticket = 100; @Override public void run() { //WindowTest2.class:类也是对象 synchronized (WindowTest2.class) { while (true) { if (ticket > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ";" + ticket--); } else { break; } } } } public static void main(String[] args) { WindowTest2 window1 = new WindowTest2(); WindowTest2 window2 = new WindowTest2(); WindowTest2 window3 = new WindowTest2(); window1.start(); window2.start(); window3.start(); } }
- synchronized(同步监视器){
-
方式二:同步方法
public class WindowTest3 {
public static void main(String[] args) {
Window3 w = new Window3();
Thread wtest1 = new Thread(w);
Thread wtest2 = new Thread(w);
Thread wtest3 = new Thread(w);
wtest1.start();
wtest2.start();
wtest3.start();
}
}
class Window3 implements Runnable {
private int ticket = 100;
Object obj = new Object();
@Override
public void run() {
while (true) {
show();
if(ticket <= 0){
break;
}
}
}
public synchronized void show() {//同步监视器:this
/**
* 如果是通过继承Thread实现,那么应改为静态方法
* public static synchronized void show(){}//同步监视器:Window3.class
*/
if (ticket > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ";" + ticket--);
}
}
}
-
总结:
- 同步方法仍然涉及到同步监视器,只是不需要我们显示的声明
- 非静态的同步方法,其同步监视器是:this
- 静态的同步方法,其同步监视器是:当前类本身
-
优缺点:
- 好处:同步的方式,解决了线程的安全问题
- 局限性:操作同步代码时,只能有一个线程参与。相当于是单线程的过程,效率降低