看了某邮件列表里的大争论,一方支持使用volatile,一方反对。反方的理由如下:
1)volatile很怪异。嗯。如果对c++很熟悉,就会觉得volatile的确是个太与众不同的关键词。c++里面并没有线程啊同步啊之类的关键词,就一个volatile孤零零摆在那里。
2)volatile在大多数平台大多数编译环境下是不起作用,在少数起作用的场合代价高昂。这点我没有测试过哈,不过的确有很多时候,在“应该”使用volatile的地方忘记加volatile关键词,程序也跑得很好。
3)如果程序不使用volatile,就会失败,说明这个程序写得很吓人。(老外的原话比这幽默n倍)解释如下:需要同步,要么线程间有共享数据,要么是为了传递某个信号(比如开始信号,或者结束信号)。前者应该用临界区保护,给临界区对象性加volatile修饰完全是多次一举,因为没有哪个编译器会“过分聪明”到知道进出临界区(典型的是一个函数,有一个地址入参)不会影响到共享数据,所以在进临界区后,一定是从内存中读数据。后者的最大问题是效率低下。虽然自旋锁的实现采用了类似的方法,但是自旋锁使用的是原子操作,不需要volatile修饰。而且自旋锁只适用于快进快出的情况。如果一个线程等待的某个变量值发生变化需要较长时间,要么很浪费CPU时间(sleep时间较短),要么可能有比较长的延宕。注意如果不sleep,在极端情况下如等待线程优先级较高,可能会造成假死锁:该变量一直无法改变。高效合理地做法是使用内核提供的同步机制,把等待线程挂起来。
注意!:上面讨论的都是多线程环境。嵌入式环境或者大量使用中断的程序,volatile有着很重要的作用。
我有保留地同意反方的观点:要慎用volatile。不过当你明白自己在做什么的时候,也未必不能用哈哈。
1)volatile很怪异。嗯。如果对c++很熟悉,就会觉得volatile的确是个太与众不同的关键词。c++里面并没有线程啊同步啊之类的关键词,就一个volatile孤零零摆在那里。
2)volatile在大多数平台大多数编译环境下是不起作用,在少数起作用的场合代价高昂。这点我没有测试过哈,不过的确有很多时候,在“应该”使用volatile的地方忘记加volatile关键词,程序也跑得很好。
3)如果程序不使用volatile,就会失败,说明这个程序写得很吓人。(老外的原话比这幽默n倍)解释如下:需要同步,要么线程间有共享数据,要么是为了传递某个信号(比如开始信号,或者结束信号)。前者应该用临界区保护,给临界区对象性加volatile修饰完全是多次一举,因为没有哪个编译器会“过分聪明”到知道进出临界区(典型的是一个函数,有一个地址入参)不会影响到共享数据,所以在进临界区后,一定是从内存中读数据。后者的最大问题是效率低下。虽然自旋锁的实现采用了类似的方法,但是自旋锁使用的是原子操作,不需要volatile修饰。而且自旋锁只适用于快进快出的情况。如果一个线程等待的某个变量值发生变化需要较长时间,要么很浪费CPU时间(sleep时间较短),要么可能有比较长的延宕。注意如果不sleep,在极端情况下如等待线程优先级较高,可能会造成假死锁:该变量一直无法改变。高效合理地做法是使用内核提供的同步机制,把等待线程挂起来。
注意!:上面讨论的都是多线程环境。嵌入式环境或者大量使用中断的程序,volatile有着很重要的作用。
我有保留地同意反方的观点:要慎用volatile。不过当你明白自己在做什么的时候,也未必不能用哈哈。