JAVA学习笔记(多线程四)——线程的安全2(线程同步机制——同步方法)
方式二:同步方法(就是在声明方法时加上synchronized关键字)(WindowsTest4,WindowsTest5演示)
如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的。
注意:
- 操作共享数据的代码,即为需要被同步的代码。—>需要被同步的代码({}中的代码)不能多也不能少
- 共享数据:多个线程共同操作的数据。(没有共享数据就不需要同步) 同步监视器:俗称‘锁’,任何一个类的对象,都可以充当锁。
- 要求:多个线程必须要共用同一把锁。(同一个类的对象)
- 补充:在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。
- 同步的方式,解决了线程的安全问题。—好处 操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。----->局限性
WindowsTest4(使用同步方法实现同步(通过实现Runnable接口的方式实现线程))
class Window4 implements Runnable{
private int ticket=100;
@Override
public void run() {
while (true){
show();
}
}
public synchronized void show(){//同步监视器(锁)this
if (ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+
":卖票,票号为:"+ticket);//Thread.currentThread().getName()本身继承了Thraed所以可以省略前面部分
ticket--;
}else {
return;
}
}
}
public class WindowsTest4 {
public static void main(String[] args) {
Window4 window=new Window4();
Thread thread1=new Thread(window);
Thread thread2=new Thread(window);
Thread thread3=new Thread(window);
thread1.setName("窗口1");
thread2.setName("窗口2");
thread3.setName("窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
WindowsTest5(使用同步方法实现同步(通过继承Thread类的方式实现线程))
class Windows5 extends Thread{
private static int ticket=100;//加了static表示这个类创建的对象共享这个数据
@Override
public void run() {
for (;;){
show();
}
}
public static synchronized void show(){//同步监视器:Windows5.class
//public synchronized void show(){//同步监视器:windows1,windows2,windows3(不符合多线程的同步要求)
if (ticket>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":卖票,票号" + ticket);
ticket--;
}
}
}
public class WindowsTest5 {
public static void main(String[] args) {
Windows5 windows1=new Windows5();
Windows5 windows2=new Windows5();
Windows5 windows3=new Windows5();
windows1.setName("窗口1");
windows2.setName("窗口2");
windows3.setName("窗口3");
windows1.start();
windows2.start();
windows3.start();
}
}