方式一:同步代码块
synchronized(同监视器){
//需要被同步的代码
}
说明:
1.操作共享数据的代码,即为需要被同步的代码。
2.共享数据:多个线程共同操作的数据。
3.同步监视器:俗称,锁。任何一个类的对象都可以充当这个锁
4.在实现类Runnable中创建多线程的方式中可以考虑用this关键字来充当锁(同步监视器),实现线程安全问题(保证使用同一把锁)
5.在Thread继承类实现多线程的方式中,慎用this关键字充当锁,可以考虑使用当前类充当同步监视器(保证使用同一把锁)
例如:Runnable实现类的方式如下处理
package com.itweiting.exer;
/**
* @Description Rannable实现多线程买票
* @User Administrator
* @Time 2021/3/29__15:38
* @
*/
class Windows implements Runnable {
private int ticket = 100;
Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (obj) {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "\t票号为:" + ticket);
ticket--;
} else {
System.out.println("票已售完");
break;
}
}
}
}
}
public class RannableSaleTicket {
public static void main(String[] args) {
//创建对象
Windows windows=new Windows();
Thread window1=new Thread(windows);
window1.setName("窗口1");
window1.start();
Thread window2=new Thread(windows);
window2.start();
window2.setName("窗口2");
Thread window3=new Thread(windows);
window3.start();
window3.setName("窗口3");
}
}
表面上看着像单线程
方式二:同步方法
同步方法总结:
1.同步方法仍需要同步监视器,只是不需要显示的声明
2.非静态的同步方法,同步监视器是:this
静态的同步方法,同步监视器是:当前类本身
例如:同步方法处理Runnable实现类的方式如下
package com.itweiting.exer;
/**
* @Description 使用同步方法解决Runnable的线程安全问题
* @User Administrator
* @Time 2021/3/29__21:02
* @
*/
class Window3 implements Runnable{
private static int ticket=100;
@Override
public void run() {
while (true) {
show();
if (ticket==0){
break;
}
}
}
public synchronized void show(){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "\t" + ticket);
ticket--;
}else{
System.out.println("票已售完");
}
}
}
public class RunnableTest1 {
public static void main(String[] args) {
Window3 window3=new Window3();
Thread t1=new Thread(window3);//第一个窗口
Thread t2=new Thread(window3);//第二个窗口
Thread t3=new Thread(window3);//第三个窗口
//给线程命名
t1.setName("线程001");
t2.setName("线程002");
t3.setName("线程003");
//启动线程
t1.start();
t2.start();
t3.start();
}
}