Java并發(fā)編程-并發(fā)編程帶來的問題

并發(fā)編程帶來的問題

1.上下文切換問題
2.死鎖問題

上下文切換

多線程不一定快

1.線程有創(chuàng)建和上下文切換的開銷

如何減少上下文切換

減少上下文切換的方法有無鎖編程、CAS算法使用最小線程、使用協(xié)程

1.無鎖并發(fā)編程,多線程競爭鎖時,會引起上下文切換,所以多線程處理數(shù)據(jù)時,可以用一些辦法來避免使用鎖,如將數(shù)據(jù)的ID按照hash算法取模分段,不同的線程處理不同段的數(shù)據(jù)
2.CAS算法。Java的Atomic包使用CAS算法來更新數(shù)據(jù),而不需要加鎖,其實也加了鎖,只不過加鎖于cpu上,系統(tǒng)開銷可忽略不計
3.使用最小線程。避免創(chuàng)建不需要的線程,比如任務很少,但是創(chuàng)建很多線程來處理,這樣會造成大量線程處于等待狀態(tài)
4.協(xié)程,在單線程里實現(xiàn)多任務調(diào)度,并在單線程里維持多個任務間的切換

死鎖

有如下代碼:

package com.fx.pattern.cor.handler;

public class DeadLockDemo {
    private static String A = "A";
    private static String B = "B";

    public static void main(String[] args) {
        new DeadLockDemo().deadLock();
    }

    private void deadLock() {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (A) {
                    try {
                        Thread.currentThread().sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (B) {
                        System.out.println('1');
                    }
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (B) {
                    synchronized (A) {
                        System.out.println('2');
                    }
                }
            }
        });

        t1.start();
        t2.start();
    }

這段代碼運行之后會引起死鎖,t1線程與t2線程互相等待對方釋放鎖。
待程序運行之后,我們采用如下方式來查看jvm對程序的跟蹤棧信息:
獲取當前程序進程id

1.ps aux | grep DeadLockDemo 

進程id如下圖所示:


DeadLockTest PID.png

獲取當前程序產(chǎn)生的堆棧信息

2.sudo -u root   jstack -F 32125 > /Users/mark/Desktop/JAVA/dump

獲取到的堆棧信息如下圖所示:


死鎖信息.png

idea中堆棧信息更加明確程序出現(xiàn)死鎖的代碼行數(shù):


死鎖分析.png

避免死鎖的方法

1.避免一個線程同時獲取多個鎖
2.避免一個線程在鎖內(nèi)同時占用多個資源,盡量保證每個鎖只占用一個資源
3.嘗試使用定時鎖,使用lock.tryLock(timeout)來代替使用內(nèi)部鎖機制。
4.對于數(shù)據(jù)庫鎖,加鎖和解鎖必須在一個數(shù)據(jù)庫連接里,否則會出現(xiàn)解鎖失敗的情況。

資源限制的挑戰(zhàn)

什么是資源限制

資源限制是指在并發(fā)編程時,程序的執(zhí)行速度受限于計算機硬件資源或軟件資源

資源限制引發(fā)的問題

并發(fā)編程,將代碼執(zhí)行速度加快的原則是將代碼中串行執(zhí)行的部分變成并發(fā)執(zhí)行,但將串行執(zhí)行的代碼演變成并發(fā)執(zhí)行,需要考慮到資源限制,資源受限的情況下,串行到并發(fā)的演變反而會使程序執(zhí)行變得更慢,因為增加了上下文切換和資源調(diào)度的時間。

如何解決資源限制問題

硬件資源限制,考慮使用集群并行執(zhí)行程序,既然單機資源有限,那就讓程序在多機上運行。
軟件資源限制,考慮使用資源池將資源復用,比如使用連接池將數(shù)據(jù)庫和Socket連接復用,或者在調(diào)用對方webService接口獲取數(shù)據(jù)時,只建立一個連接。

在資源限制情況下進行并發(fā)編程

1.根據(jù)不同的資源限制調(diào)整程序的并發(fā)度。涉及數(shù)據(jù)庫連接數(shù)的sql操作,如果sql語句執(zhí)行非???,但是線程數(shù)量比數(shù)據(jù)庫連接大很多,則某些線程會被阻塞,等待數(shù)據(jù)庫連接。

博客搬家:大坤的個人博客
歡迎評論哦~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容