天天看點

七日打卡--java并發程式設計之上下文切換

上下文切換

CPU通過時間片配置設定算法來循環執行任務,目前任務執行一個時間片後會切換到下一個任務。但是在切換前會儲存上一個任務的狀态,以便下次切換回這個任務時,可以再加載這個任務的狀态。是以任務從儲存到再加載的過程就是一次上下文切換。

并發執行不一定比串行執行快,因為線程有建立和上下文切換的開銷。

減少上下文切換的方法有:

  • 無鎖并發程式設計:多線程競争鎖時,會引起上下文切換,可以用一 些辦法來避免使用鎖,如将資料的ID按照Hash算法取模分段,不同的線程處理不同段的資料
  • CAS算法(compare-and-swap):Java的Atomic包使用CAS算法來更新資料,而不需要加鎖
    public class AtomicCounter {  private final AtomicInteger counter = new AtomicInteger(0);  public int getValue() {return counter.get();
        }public void increment() {while(true) {int existingValue = getValue();int newValue = existingValue + 1;if(counter.compareAndSet(existingValue, newValue)) {return;
                }
            }
        }
    }複制代碼      
  • 使用最少線程:避免建立不需要的線程,比如任務很少,但是建立了很多線程來處理,這樣會造成大量線程都處于等待狀态
  • 協程(Quasar):在單線程裡實作多任務的排程,并在單線程裡維持多個任務間的切換

死鎖

鎖是個非常有用的工具,運用場景非常多,因為它使用起來非常簡單,而且易于了解。但同時它也會帶來一些困擾,那就是可能會引起死鎖,一旦産生死鎖,就會造成系統功能不可用。

避免死鎖的幾種常見方法:

  • 避免一個線程同時擷取多個鎖
  • 避免一個線程在鎖内同時占用多個資源,盡量保證每個鎖隻占用一個資源
  • 嘗試使用定時鎖,使用lock.tryLock(timeout)來替代使用内部鎖機制
  • 對于資料庫鎖,加鎖和解鎖必須在一個資料庫連接配接裡,否則會出現解鎖失敗的情況

資源限制

  • 帶寬的上傳/下載下傳速度
  • 硬碟讀寫速度
  • CPU的處理速度
  • 資料庫的連接配接數
  • socket連接配接數等

繼續閱讀