傅里叶变换总结及FFT画图横坐标设置
2026/11/1 1:59:07
| 维度 | Java AQS | Golang Channel |
|---|---|---|
| 本质 | 同步器框架 | 通信原语 |
| 哲学 | 共享内存同步 线程通过共享状态通信 | CSP 模型 通过通信共享内存 |
| 主要目的 | 构建各种锁和同步工具 | Goroutine 间数据传输和同步 |
| 使用场景 | 资源访问控制、线程协调 | 协程间消息传递、流水线 |
// AQS 像是 银行排队叫号系统publicclassAQSBank{privateintstate;// 柜台数量(资源数)privateQueue<Thread>queue;// 等待队列publicvoidacquire(){if(state>0){state--;// 有空柜台,直接办理}else{queue.add(Thread.currentThread());// 排队等待LockSupport.park();// 线程挂起}}publicvoidrelease(){state++;if(!queue.isEmpty()){Threadt=queue.poll();LockSupport.unpark(t);// 叫号}}}// Channel 像是 工厂流水线传送带funcPipelineExample(){ch:=make(chanint,3)// 容量为3的缓冲区// 生产者:放产品到传送带gofunc(){fori:=0;i<10;i++{ch<-i// 如果传送带满,阻塞等待fmt.Printf("生产: %d\n",i)}close(ch)}()// 消费者:从传送带取产品gofunc(){foritem:=rangech{fmt.Printf("消费: %d\n",item)time.Sleep(100*time.Millisecond)}}()}// 典型 AQS 使用场景:实现一个连接池publicclassConnectionPool{privatefinalSemaphoresemaphore;// 基于 AQSpublicConnectionPool(intsize){semaphore=newSemaphore(size);}publicConnectiongetConnection()throwsInterruptedException{semaphore.acquire();// 获取许可(如果没有就等待)returncreateConnection();}publicvoidreleaseConnection(Connectionconn){closeConnection(conn);semaphore.release();// 释放许可}}// Channel 典型场景:工作池模式funcWorkerPool(){jobs:=make(chanJob,100)// 工作队列results:=make(chanResult,100)// 结果队列// 启动工作协程forw:=1;w<=3;w++{goworker(w,jobs,results)}// 分发工作forj:=1;j<=9;j++{jobs<-Job{ID:j}}close(jobs)// 收集结果forr:=1;r<=9;r++{<-results}}funcworker(idint,jobs<-chanJob,resultschan<-Result){forjob:=rangejobs{// 自动阻塞等待工作result:=process(job)results<-result// 发送结果}}| 特性 | Java AQS | Golang Channel |
|---|---|---|
| 并发模型 | 多线程共享内存 | 多协程 CSP 通信 |
| 阻塞方式 | 显式park()/unpark() | 隐式(读写时自动) |
| 队列类型 | 单向链表(CLH变体) | 环形缓冲区或有缓冲/无缓冲 |
| 等待策略 | FIFO(公平)或插队(非公平) | FIFO |
| 资源管理 | 通过 state 变量显式控制 | 通过缓冲区容量隐式控制 |
| 数据类型 | 通常用于同步状态(int) | 可以传输任意类型数据 |
| 多路复用 | 需要自己实现(如 Condition) | 内置select多路复用 |
| 错误处理 | 显式异常处理(InterruptedException) | 通过 channel 状态(关闭检测) |
// Java AQS - CountDownLatch(同步点)CountDownLatchlatch=newCountDownLatch(3);// Golang Channel - WaitGroup 模式(类似功能)varwgsync.WaitGroupwg.Add(3)// 用 Channel 实现 CountDownLatch 功能funcchannelAsLatch(){done:=make(chanbool,1)fori:=0;i<3;i++{gofunc(idint){// 工作...ifid==2{// 最后一个完成done<-true// 类似 countDown()}}(i)}<-done// 类似 await()close(done)}// Java AQS + Condition(等待/通知)ReentrantLocklock=newReentrantLock();Conditioncondition=lock.newCondition();lock.lock();try{while(!conditionMet){condition.await();// 释放锁并等待}// 条件满足,继续执行}finally{lock.unlock();}// Golang Channel(等待/通知)funcchannelAsCondition(){ch:=make(chanstruct{})// 无缓冲 channelgofunc(){// 等待条件<-ch// 阻塞直到有数据fmt.Println("条件满足!")}()// 触发条件time.Sleep(time.Second)ch<-struct{}{}// 发送信号close(ch)}publicclassProducerConsumerAQS{privatefinalReentrantLocklock=newReentrantLock();privatefinalConditionnotFull=lock.newCondition();privatefinalConditionnotEmpty=lock.newCondition();privatefinalQueue<Integer>queue=newLinkedList<>();privatefinalintcapacity;publicvoidproduce(intitem)throwsInterruptedException{lock.lock();try{while(queue.size()==capacity){notFull.await();// 队列满,等待}queue.offer(item);notEmpty.signal();// 通知消费者}finally{lock.unlock();}}publicIntegerconsume()throwsInterruptedException{lock.lock();try{while(queue.isEmpty()){notEmpty.await();// 队列空,等待}Integeritem=queue.poll();notFull.signal();// 通知生产者returnitem;}finally{lock.unlock();}}}funcProducerConsumerChannel(){ch:=make(chanint,10)// 缓冲 channel 自动同步// 生产者gofunc(){fori:=0;i<100;i++{ch<-i// 自动阻塞如果缓冲区满fmt.Printf("生产: %d\n",i)}close(ch)}()// 消费者gofunc(){foritem:=rangech{// 自动阻塞如果缓冲区空fmt.Printf("消费: %d\n",item)time.Sleep(50*time.Millisecond)}}()}AQS:我是交通警察,指挥线程有序访问共享资源
Channel:我是快递小哥,在协程间传递包裹
两者都是优秀的并发工具,但设计哲学不同:AQS 更偏向"控制",Channel 更偏向"通信"。理解这种差异有助于在正确的场景选择正确的工具。