- 论坛徽章:
- 2
|
回复 7# AD8018
thread_id有问题。 且不说没有初始化是垃圾值。
thread1:
lock_r(&m);
unlock_r(&m);
此时 thread_id=thread1
thread1:
lock_r(&m);
if 测试成功
切换
thread2:
lock_r(&m);
if 测试失败
lock成功, 此时被thread2持有。
thread1:
继续执行++count。 且返回。
此时 thread1 与 thread2 都没有被block。
------ ------ ------ reset owner ------ ------ -------
无论 owner 一开始被设置为何值。
在unlock, count==0 时被设置为何值。
只要这个值会和某个thread_id重复, 那还是有上述问题。
lock中if (owner==thread_id()) 成功, 但其实该线程并没有持有锁。
------ ------ ------ invalid thread id ------ ------ -------
绝对不会出现的thread_id。
Windows上是有的, 0不会被作为线程号。
非Windows上我就不了解了。
pthread_t 甚至不一定是整数:
- IEEE Std 1003.1-2001/Cor 2-2004, item XBD/TC2/D6/26 is applied, adding pthread_t to the list of types that are not required to be arithmetic types, thus allowing pthread_t to be defined as a structure.
复制代码 先姑且假设这个号存在, thread_id() 返回一定不会和它相同。
无论是 if (owner==thread_id()) // owned by this thread, ++count
还是 if (owner==invalid_id) // available, owner=thread_id
测试与后面的操作都不是原子的。
都可能会出现测试成功, 然后被切换, 使得另一个线程也测试成功。
这里需要一个原子操作:
- int compare_and_swap(int* dst, int test, int set)
- {
- int old = *dst;
- if (old == test) *dst = set;
- return old;
- }
复制代码 那么就可以:
id = thread_id();
x = CAS(&owner, invalid_id, id);
if (x==invalid_id) // available -> owned by this thread
...
else if (x==id) // already owned by this thread
...
else // owned by other thread
...
再回到非Windows。
CAS以及其他 atomic 也没有被posix定义。
即使定义了, pthread_t 也不一定是整数。
而且是属于改动后对实现放宽了限制。
这和改动后加强了对实现的限制不同。
比如C99 , 新增加了所有的 struct(union)的指针都有相同的对齐与大小, 这是C89中没有的。
也就是说, 即使在C89中也可以假设 struct 的指针有相同的大小与对齐(那些不满足的实现可能已经被历史淘汰了)。
改动后对实现放宽了限制, 可能确实有实现不满足原有的限制 —— 这只是我的猜测了。 |
|