Go語言多線程問題

打印零與奇偶數(leetcode 1116)

方法1:使用互斥鎖和條件變量

package mainimport ("fmt""sync"
)type ZeroEvenOdd struct {n         intzeroMutex sync.MutexevenMutex sync.MutexoddMutex  sync.Mutexcurrent   int
}func NewZeroEvenOdd(n int) *ZeroEvenOdd {z := &ZeroEvenOdd{n: n}z.evenMutex.Lock()z.oddMutex.Lock()return z
}func (z *ZeroEvenOdd) Zero(printNumber func(int)) {for i := 0; i < z.n; i++ {z.zeroMutex.Lock()printNumber(0)z.current++if z.current%2 == 1 {z.oddMutex.Unlock()} else {z.evenMutex.Unlock()}}
}func (z *ZeroEvenOdd) Even(printNumber func(int)) {for i := 2; i <= z.n; i += 2 {z.evenMutex.Lock()printNumber(i)z.zeroMutex.Unlock()}
}func (z *ZeroEvenOdd) Odd(printNumber func(int)) {for i := 1; i <= z.n; i += 2 {z.oddMutex.Lock()printNumber(i)z.zeroMutex.Unlock()}
}func main() {n := 5zeo := NewZeroEvenOdd(n)var wg sync.WaitGroupwg.Add(3)printFunc := func(x int) {fmt.Print(x)}go func() {defer wg.Done()zeo.Zero(printFunc)}()go func() {defer wg.Done()zeo.Even(printFunc)}()go func() {defer wg.Done()zeo.Odd(printFunc)}()wg.Wait()fmt.Println()
}

方法2:使用通道同步

package mainimport ("fmt""sync"
)type ZeroEvenOdd struct {n       intzeroCh  chan struct{}evenCh  chan struct{}oddCh   chan struct{}done    chan struct{}
}func NewZeroEvenOdd(n int) *ZeroEvenOdd {z := &ZeroEvenOdd{n:      n,zeroCh: make(chan struct{}),evenCh: make(chan struct{}),oddCh:  make(chan struct{}),done:   make(chan struct{}),}close(z.zeroCh) // 初始允許zero執行return z
}func (z *ZeroEvenOdd) Zero(printNumber func(int)) {for i := 0; i < z.n; i++ {<-z.zeroChprintNumber(0)if i%2 == 0 {z.oddCh <- struct{}{}} else {z.evenCh <- struct{}{}}}close(z.done)
}func (z *ZeroEvenOdd) Even(printNumber func(int)) {for i := 2; i <= z.n; i += 2 {<-z.evenChprintNumber(i)z.zeroCh <- struct{}{}}
}func (z *ZeroEvenOdd) Odd(printNumber func(int)) {for i := 1; i <= z.n; i += 2 {<-z.oddChprintNumber(i)z.zeroCh <- struct{}{}}
}func main() {n := 5zeo := NewZeroEvenOdd(n)var wg sync.WaitGroupwg.Add(3)printFunc := func(x int) {fmt.Print(x)}go func() {defer wg.Done()zeo.Zero(printFunc)}()go func() {defer wg.Done()zeo.Even(printFunc)}()go func() {defer wg.Done()zeo.Odd(printFunc)}()wg.Wait()fmt.Println()
}

方法3:使用原子計數器

package mainimport ("fmt""sync""sync/atomic"
)type ZeroEvenOdd struct {n       intcurrent int32cond    *sync.Cond
}func NewZeroEvenOdd(n int) *ZeroEvenOdd {return &ZeroEvenOdd{n:       n,current: 0,cond:    sync.NewCond(&sync.Mutex{}),}
}func (z *ZeroEvenOdd) Zero(printNumber func(int)) {for i := 0; i < z.n; i++ {z.cond.L.Lock()for atomic.LoadInt32(&z.current) != 0 {z.cond.Wait()}printNumber(0)atomic.StoreInt32(&z.current, int32(i+1))z.cond.Broadcast()z.cond.L.Unlock()}
}func (z *ZeroEvenOdd) Even(printNumber func(int)) {for i := 2; i <= z.n; i += 2 {z.cond.L.Lock()for atomic.LoadInt32(&z.current) != int32(i) {z.cond.Wait()}printNumber(i)atomic.StoreInt32(&z.current, 0)z.cond.Broadcast()z.cond.L.Unlock()}
}func (z *ZeroEvenOdd) Odd(printNumber func(int)) {for i := 1; i <= z.n; i += 2 {z.cond.L.Lock()for atomic.LoadInt32(&z.current) != int32(i) {z.cond.Wait()}printNumber(i)atomic.StoreInt32(&z.current, 0)z.cond.Broadcast()z.cond.L.Unlock()}
}func main() {n := 5zeo := NewZeroEvenOdd(n)var wg sync.WaitGroupwg.Add(3)printFunc := func(x int) {fmt.Print(x)}go func() {defer wg.Done()zeo.Zero(printFunc)}()go func() {defer wg.Done()zeo.Even(printFunc)}()go func() {defer wg.Done()zeo.Odd(printFunc)}()wg.Wait()fmt.Println()
}

哲學家進食

package mainimport ("fmt""sync""time"
)const numPhilosophers = 5type Philosopher struct {id          intleftFork    *sync.MutexrightFork   *sync.MutexeatingTimes int
}func (p *Philosopher) think() {fmt.Printf("哲學家 %d 正在思考...\n", p.id)time.Sleep(time.Second * 1)
}func (p *Philosopher) eat() {// 確定拿叉子的順序(避免循環等待)first, second := p.leftFork, p.rightForkif p.id%2 == 0 { // 偶數ID哲學家先拿右叉子first, second = p.rightFork, p.leftFork}// 獲取叉子first.Lock()second.Lock()// 進餐fmt.Printf("哲學家 %d 開始進餐 (第%d次)\n", p.id, p.eatingTimes+1)time.Sleep(time.Second * 1)p.eatingTimes++// 釋放叉子second.Unlock()first.Unlock()
}func (p *Philosopher) dine(sem chan struct{}, wg *sync.WaitGroup) {defer wg.Done()for i := 0; i < 3; i++ { // 每個哲學家吃3次便于觀察p.think()// 獲取就餐許可sem <- struct{}{}p.eat()<-sem}
}func main() {// 初始化叉子forks := make([]*sync.Mutex, numPhilosophers)for i := range forks {forks[i] = &sync.Mutex{}}// 創建哲學家philosophers := make([]*Philosopher, numPhilosophers)for i := range philosophers {philosophers[i] = &Philosopher{id:        i,leftFork:  forks[i],rightFork: forks[(i+1)%numPhilosophers],}}// 使用信號量限制同時就餐人數(最多允許4人同時嘗試拿叉子)sem := make(chan struct{}, numPhilosophers-1)var wg sync.WaitGroup// 開始就餐for _, p := range philosophers {wg.Add(1)go p.dine(sem, &wg)}wg.Wait()// 統計每位哲學家就餐次數for _, p := range philosophers {fmt.Printf("哲學家 %d 總共進餐 %d 次\n", p.id, p.eatingTimes)}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83368.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83368.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83368.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ateⅹⅰt()的用法

在C/C++中, atexit() 函數用于注冊程序退出時需要調用的函數,即使程序通過 main() 函數返回、 exit() 函數退出或異常終止,這些注冊的函數也會被執行。以下是其詳細用法: 1. 函數原型與頭文件 #include <cstdlib> // C++中需包含此頭文件 int atexit(void (*functio…

【大模型】 使用llama.cpp 進行模型轉換和量化

目錄 1 相關知識 ■llama.cpp ■GGUF 格式 ■量化 2 詳細步驟 克隆 llama.cpp 倉庫 安裝依賴 配置 CMake 構建 構建項目 驗證安裝 轉換 safetensors 為 FP16 GGUF 量化模型 (Q4_K_M) 測試量化模型 1 相關知識 ■llama.cpp llama.cpp是一個開源的 C/C++ 庫,旨…

大數據學習(133)-Hive數據分析2

????&#x1f34b;&#x1f34b;大數據學習&#x1f34b;&#x1f34b; &#x1f525;系列專欄&#xff1a; &#x1f451;哲學語錄: 用力所能及&#xff0c;改變世界。 &#x1f496;如果覺得博主的文章還不錯的話&#xff0c;請點贊&#x1f44d;收藏??留言&#x1f4…

IDEA 連接 Docker 一鍵打鏡像

首先&#xff0c;檢查 IDEA 是否安裝了 Docker 插件&#xff1a; 版本比較新的 IDEA 默認都安裝了這個插件&#xff0c;如果沒有安裝&#xff0c;安裝一下。 確保我們虛擬機上安裝了 Docker 和 Docker-compose&#xff0c;并啟動了 Docker。 找到 IDEA 下方的 Services tab 欄…

第六講——一元函數微分學的應用之中值定理、微分等式與微分不等式

文章目錄 連續函數性質定理定理1 有界與最值定理定理2 介值定理定理3 平均值定理定理4 零點定理定理5 費馬定理導數介值定理(達布定理) 中值定理羅爾定理拉格朗日中值定理柯西中值定理泰勒公式 討論方程的根問題——微分等式證明不等式問題使用函數的性質(單調性、凹凸性、最值…

2025.06.11【Ribo-seq】|用CPAT預測sORF序列的編碼潛能

文章目錄 前言一、準備工作1. 安裝CPAT2. 下載物種特異性模型 二、準備sORF核酸序列1. 獲取sORF的拼接核酸序列示例腳本&#xff08;假設已獲得外顯子fasta&#xff09;&#xff1a; 三、運行CPAT預測編碼潛能1. 準備CPAT模型和hexamer表2. 運行CPAT 四、結果解讀五、常見問題與…

Hive面試題匯總

一、hive架構相關 遇到這類問題&#xff0c;可以靈活的去回答&#xff0c;比如可以結合平時使用hive的經驗作答&#xff0c;也可以結合下圖從數據的讀入、解析、元數據的管理&#xff0c;數據的存儲等角度回答&#xff1a; 二、hive的特點 本題主要為了考察對hive的整體使用…

樹莓派超全系列教程文檔--(57)如何設置 Apache web 服務器

如何設置 Apache web 服務器 設置 Apache web 服務器安裝 Apache測試 web 服務器更改默認網頁 為 Apache 安裝 PHP 文章來源&#xff1a; http://raspberry.dns8844.cn/documentation 原文網址 設置 Apache web 服務器 Apache 是一款流行的 web 服務器應用程序&#xff0c;您…

(九)現代循環神經網絡(RNN):從注意力增強到神經架構搜索的深度學習演進

現代循環神經網絡的內容&#xff0c;將介紹幾種先進的循環神經網絡架構&#xff0c;包括門控循環單元&#xff08;GRU&#xff09;、長短期記憶網絡&#xff08;LSTM&#xff09;的變體&#xff0c;以及注意力機制等。這些內容將幫助你更深入地理解循環神經網絡的發展和應用。 …

牛市與熊市:市場周期的雙面鏡

牛市推動資產增值與風險積累&#xff0c;熊市擠壓泡沫并孕育機會&#xff0c;兩者交替循環&#xff0c;構成市場自我調節機制。 1、概念對比&#xff1a;情緒與趨勢的博弈 牛市&#xff08;Bull Market&#xff09;&#xff1a;指資產價格持續上漲&#xff08;通常漲幅超20%&a…

web程序設計期末復習-填空題

常用標簽 塊級標記 行內標記等 一、塊級元素 特點&#xff1a; 獨占一行可以設置寬度、高度、內外邊距默認情況下會從上到下垂直排列 常見標簽&#xff1a; 標簽 含義 <div> 最常用的通用塊級容器 <p> 段落 <h1>到<h6> 標題&#xff08;一級…

go全局配置redis,全局只需要連接一次,然后全局可以引用使用

創建redis文件夾、創建dadeRedis.go package redisimport ("context""github.com/go-redis/redis/v8""log""time" )var (client *redis.Clientctx context.Background() )// 初始化Redis連接&#xff08;建議在程序啟動時調用&am…

緩沖區(C語言緩沖區+內核緩沖區)一個例子解釋他們的關系和作用!!!

首先提出問題&#xff1a; 為什么以下代碼是先sleep三秒后&#xff0c;屏幕才顯示"XXXXXXX"。 #include<stdio.h> #include<unistd.h>int main() {printf("XXXXXXX");sleep(3);return 0; } 為什么以下代碼是先顯示"XXXXXXX"&#xf…

【2025版】Java 工程師學習路線圖 —— 掌握程度描述版

?【2025版】Java 工程師學習路線圖 &#x1f4a1; 目標&#xff1a;成為合格的 Java 工程師&#xff08;前后端都要會&#xff09; &#x1f4dd; 結構清晰 | 階段明確 | 掌握程度分級 | 適合自學或轉行 &#x1f539; 階段一&#xff1a;編程基礎 計算機通識 模塊內容推薦掌…

從零實現一個紅隊智能體

從零實現一個紅隊智能體(持續更新) 2025-06-09 背景&#xff1a;最近學了基礎些東西和工具基礎使用&#xff0c;發現一套流程下來太多需要手工要做的&#xff0c;就像自己能不能結合自己的技術棧實現小工具 &#x1f947; 第一步&#xff1a;從實用性開始分析 目標場景 希望…

Uniapp實現多選下拉框

文章目錄 前言一、效果展示1.1 下拉效果圖1.2 下拉選擇效果圖1.3 選擇顯示效果圖 二、組件源碼2.1.CustomCheckbox.vue源碼2.2.niceui-popup-select.vue源碼 三、demo.vue代碼演示 前言 之前在使用Uniapp時&#xff0c;一直都是下拉框單選。今天某個項目需求需要使用Uniapp實現…

JavaScript-Array.from

Array.from() 是 JavaScript 中用于將類數組對象&#xff08;array-like&#xff09;或可迭代對象&#xff08;iterable&#xff09;轉換為真實數組的一個非常有用的方法。 &#x1f4cc; 一、基本語法 Array.from(arrayLike, mapFn?, thisArg?)參數說明&#xff1a; 參數類…

二刷蒼穹外賣 day02

新增員工 DTO 將前端傳遞的參數列表通過對應的實體類接收 當前端提交的數據和實體類中對應的屬性差別較大時&#xff0c;使用DTO來封裝數據 Data public class EmployeeDTO implements Serializable {private Long id;private String username;private String name;private…

通過Heron Handoff 插件我們在figma設計中可以像sketch導出離線標注

一、設計交付的歷史困境與破局契機 在數字產品開發的全流程中&#xff0c;設計標注的高效傳遞始終是連接創意與實現的關鍵紐帶。傳統設計工具如 Sketch 憑借 Bluebeam、Sketch Measure 等插件構建了成熟的離線標注體系&#xff0c;設計師可將標注文件打包交付&#xff0c;開發…

SSE 數據的傳輸無法流式獲取

問題 調試過程中發現SSE數據返回的時間都是一樣的&#xff0c;懷疑是接口問題。 參考 EventSource數據一次性出來&#xff0c;并未流式輸出的原因_sourceevent為什么結果一下全部返回了-CSDN博客 處理 EventStream 不能流式返回的問題&#xff1a;Nginx 配置優化 解決方案 …