并發: 同一個物件被多個執行緒同時操作;
1.由于同一行程的多個執行緒共享同一塊存盤空間,會發生訪問沖突問題.為了訪問的正確性,在訪問時加入了鎖機制(synchronized) ,當一個執行緒獲得物件的排它鎖時,獨占資源,其他執行緒必須等待,使用后釋放鎖即可,
2.一個執行緒持有鎖會導致其他所有需要此鎖的執行緒掛起;
3.在多執行緒競爭下,加鎖,釋放鎖會導致比較多的背景關系切換和調度延時,引起性能問題;
4.如果一個優先級高的執行緒等待一個優先級低的執行緒釋放鎖,會導致優先級倒置,引起性能問題
1.搶票不安全問題
//多個執行緒處理同一資源時,執行緒不安全會出現資料紊亂
public class UnsafeBuyTicket {
public static void main(String[] args) {
Myticket myticket = new Myticket();
new Thread(myticket,"用戶1").start();
new Thread(myticket,"用戶2").start();
new Thread(myticket,"用戶3").start();
}
}
//買票的類
class Myticket implements Runnable{
private int tickets = 10;//設定總票數
boolean flag = true;//采用外部停止的方式
@Override
public void run() {//run()方法的作用是票未搶完時,不斷更新搶票的狀態
//買票
while (flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//判斷是否有票
private void buy() throws InterruptedException {
while (flag){
if(tickets<=0) {
flag = false;
return;
}
//模擬延時
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"搶到了第"+tickets--+"張票");}
}
搶票結果會出現負數,執行緒不安全

2.同時取錢不安全
實作思路:
1.先創建賬戶,包含賬戶名字和余額兩個變數,為實作接收輸入-構造器
2創建取款類并繼承Thread類,銀行取款流程:賬戶資訊+取款金額+判斷余額是否大于取款金額,實作多個執行緒同時取款繼承Thread類-重寫run()方法
3.在main()方法要給Thread類中傳遞名字,在Thread的子類構造器第一行呼叫super(name);
4.在run()方法中具體實作余額判斷更新
//不安全事件
//模擬銀行取錢
public class UnsafaBank {
public static void main(String[] args) {
Account account = new Account(100,"卡內");
Drawing drawing01 = new Drawing(account,50,"用戶1");
Drawing drawing02 = new Drawing(account,100,"用戶2");
drawing01.start();
drawing02.start();
}
}
//銀行賬戶
class Account{
int money;
String name;
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//銀行 模擬取錢
class Drawing extends Thread{
Account account;//賬戶
//取了多少錢
int drawingmoney;
//現在手里有多少錢
int nowmoney;
public Drawing(Account account,int drawingmoney,String name){
super(name);
this.account = account;
this.drawingmoney = drawingmoney;
}
//取錢
@Override
public void run() {
//判斷賬戶的錢是否夠用戶取出的錢
if(account.money-drawingmoney<0){
System.out.println(Thread.currentThread().getName()+"錢不夠,請修改金額");
return;
}
//模擬延時,放大問題的發生性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//賬戶剩余的錢
account.money = account.money-drawingmoney;
//手里的錢
nowmoney = nowmoney+drawingmoney;
//輸出賬戶的錢
System.out.println(account.name+"余額為:"+account.money);
//輸出用戶拿到的錢
System.out.println(Thread.currentThread().getName()+"取出"+nowmoney);
}
}
執行緒不安全,兩個執行緒同時對一個資源操作時,出現余額為負數

3.執行緒不安全
List是Java中比較常用的集合類,關于List介面有很多實作類,其中幾個重點的實作是ArrayList、LinkedList和Vector
//執行緒不安全
public class UnsafeList {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
//同時創建10000個線性,使用Lambda
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}

之所以list集合沒有10000個元素,有可能多個執行緒同時將執行緒名加入串列導致覆寫
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/283179.html
標籤:其他
上一篇:運維實戰 Nginx配置優化
下一篇:node.js 的模塊化開發規范
