Java并发研究 自己写ReentrantLock和ReentrantReadWriteLock(4)

上篇。在写完ReentrantLock之后,其实可以基于ReentrantLock写一个ReadWriteLock,《the art of multiprocessor programming》第八章有介绍。但是,本着不完全AQS(AbstractQueuedSynchronizer)介绍的系列主题,这里从零开始重新写一个ReentrantReadWriteLock。

按照ReadWriteLock的定义,任何时候都满足

  1. 没有线程持有锁
  2. 有1~n个线程持有共享锁(Read)
  3. 有1个线程持有独占锁(Write)

中的一个。

其次公平的ReadWriteLock要求新来的Read或者Write线程必须在队列中等待,非公平的ReadWriteLock允许新来的Read或者Write比队列中等待的线程先获取锁。关于非公平锁这里多说一句,理论上的非公平锁类似一群人哄抢的现象,但是实现多半是只允许新来和线程队列最前面的线程抢占锁。ReadWriteLock也是一样。如果你想要完全非公平的锁的话,可能AQS和这里的实现不满足你的需求。

为了实现ReadWriteLock的定义,你需要分别记录读写状态。考虑到独占(Write)状态只可能有一个线程,可能场景如下:

Read More

raspberry pi 3 b+ cross compile on macos mojave

本文记录了如何在mojave上构建raspberry pi 3 b+的交叉编译环境。交叉编译的原因最主要的还是速度,当然还有目标平台没有直接的编译工具链等。在构建交叉编译环境之前,最好确认目标平台的相关信息,能直接确认目标平台的工具链是最好的,因为从CPU判断可能并不准确。

比如raspebrry pi 3 b+,自带gcc,相关信息如下

注意其中target为arm-linux-gnueabihf。假如从raspberry pi 3 b+的CPU(Broadcom BCM2837 64bit CPU)判断的话,armv8,aarch64貌似都可以用,但实际用aarch64架构编译出来的程序无法在raspberry pi,准确来说是安装了raspbian上的raspberry pi上执行,这点请注意(假如想在raspberry pi 3 b+上执行aarch64架构的程序的话,个人觉得可能要换raspbian以外的系统,或者修改内核编译选项,这块等自己有空尝试并成功了再发出来)。

Read More

Compile and install valgrind on macOS Mojave (10.14.2)

本文是给想在Mojave上编译安装valgrind的人一个参考。

个人因为《Hands on concurrency with Rust》这本书的原因,需要安装valgrind。但是现在(2019/2/9)稳定版本的valgrind尚未支持Mojave,即不能通过Homebrew安装。valgrind的bug tracker里有这个问题的追踪, 但是看状态估计离正式发布还需要时间(开源项目常有的事情,缺少资源,哎)。对话中给了一个github上的commit,看起来可以使用。

下载对应的repository,checkout到修改版的branch上

按照valgrind自身网站上的说明,接下来是常规的compile install。

如果你按照顺序执行的话,在make可能会碰到如下两个问题,所以在执行之前,建议先看一下可能碰到的问题

1. No rule to make target `/usr/include/mach/mach_vm.defs’

简单来说,就是没有找到定义文件。按照stackoverflow上一个问题的说法,你可以通过

解决,但是答案针对的不是Mojave,所以Mojave除了通过上述命令安装XCode之外,还需要解答中另外一个解决方案,即修改coregrind/Makefile(此文件在./configure之后生成)中mach_vm.defs的路径,具体如下

也就是在原本 /usr/include/mach/mach_vm.defs 等文件前加上 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk 前缀,你可以 ls 一下看一下文件是否存在。

2. vgpreload_core_x86_darwin_so-vg_preloaded.o ld: symbol(s) not found for architecture i386

这个问题比较隐蔽,google搜不出来什么东西。直接看错误信息的话,大概知道MacOS下无法链接i386的程序,因为比较新的MacOS基本上只有x86_64。直接的解决方法是不让valgrind去编译i386架构的程序。

如果你留意了 ./configure 最后的输出的话,可以看到Secondary build arch

假如Secondary build arch不像上面那样为空的话,比如是i386,那么make时会出现以上问题。

在 configure 文件中,valgrind的注释提到在MacOS下会同时编译i386和x86_64,这是问题的根本原因,或者说valgrind在Mojave下编译的坑。幸好 configure 提供了只编译64位的选项,不需要修改 configure 文件。

总结一下,你要做的是

小结

老实说很后悔升级到了Mojave,MacBook的睡死,突然mic不能使用等问题,现在又来一个valgrind……

不管怎么说,希望本文对你有所帮助。

 

 

如何理解 C++11 原子变量(Atomic)的 Memory Order

最近几天在学习Rust,把Rust官网附带的The Rust Programming Language看完,开始尝试用Rust实现自己学习过的并发数据结构。首先碰到的问题是,如何理解Rust所基于的LLVM的atomics模型。因为LLVM的原子变量模型基本可以对应于C++11开始的原子变量,除了没有consume memory order。所以任务就变成了如何理解C++11的原子变量。

C++原子变量本身并不难理解,但是理解memory order很难。网上找了很多资料,都没有很清晰得解释memory order到底是什么。今天重新看了《C++ Concurrency in Action》关于memory order的部分,对照着 std::memory_order 的介绍,突然明白了这是怎么一回事。

答案是memory order就只是一个order。

Read More