在Java中,我們通過同步機制,來解決線程的安全問題
解決方法:
方式一:同步代碼塊
操作共享數(shù)據(jù)的代碼,即為需要被同步的代碼
共享數(shù)據(jù):多個線程共同操作的變量。比如:ticket
同步監(jiān)視器,俗稱鎖。任何一個類的對象都可以成為鎖
要求:多個線程必須要共用同一把鎖 保證唯一性
補充:在實現(xiàn)Runnable接口創(chuàng)建多線程的方式中,我們可以考慮使用this充當同步監(jiān)視器。但!慎用this充當同步監(jiān)視器
考慮使用當前類充當同步監(jiān)視器。
方式二:同步方法
如果操作共享數(shù)據(jù)的代碼完整聲明在一個方法中,我們不妨將此方法聲明同步
總結(jié):1. 同步方法仍然涉及到同步監(jiān)視器,只是不需要我們顯示的聲明
2. 非靜態(tài)的同步方法,同步監(jiān)視器是:this
靜態(tài)的同步方法,同步監(jiān)視器是當前類本身
同步的方式,解決了線程的安全問題 但是!操作同步代碼時,只能有一個線程參與,其他線程等待。相當于是一個單線程的過程,效率低。
原則:共用同一把鎖
方式一:同步代碼塊
①Runnable()接口實現(xiàn)的多線程
@Override
public void run() {
while (true) {
synchronized (this) { //此時的this:唯一的Window2的對象 //方式二 synchronized (obj)
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() " 賣票 票號為: " ticket);
ticket--;
} else {
break;
}
}
}
}
}
②繼承方式實現(xiàn)多線程
public void run() {
while (true) {
synchronized (Window2.class) { //錯誤的方式:synchronized (this) 這里的this有三個對象 鎖必須共用
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() " 賣票 票號為: " ticket);
ticket--;
} else {
break;
}
}
}
}
方式二:同步方法
①Runnable()接口實現(xiàn)的多線程
class Window3 implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
show();
if (ticket < 1){
break;
}
}
}
private synchronized void show(){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() " 賣票 票號為: " ticket);
ticket--;
}
}
}
②繼承方式實現(xiàn)多線程
class Window extends Thread{
private static int ticket = 100;
@Override
public void run() {
while (true) {
show();
if (ticket < 1){
break;
}
}
}
private static synchronized void show(){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() " 賣票 票號為: " ticket);
ticket--;
}
}
}
來源:https://www.icode9.com/content-4-870451.html