Matthew Note

Multiple Thread & Thread Safety

Multiple Thread

pthread_mutex

有两种方式创建一个mutex一种是静态方法,一种是动态方法,似乎静态方法不需要Destroy???

1
2
3
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock;
pthread_mutex_init (&lock, NULL);

pthread_cancel

1
2
3
4
int pthread_cancel(pthread_t thread);
int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);
void pthread_testcancel(void); [Option End]

cancel,用来取消一个线程,但是按照默认的配置他是不会立刻退出的,会在cancelpoint选择退出。取消点是在程序在运行的时候检测是否收到取消请求,是否允许允许操作执行的点。下面的POSIX线程函数就是取消点:

1
2
3
4
5
6
7
pthread_join()
pthread_cond_wait()
pthread_cond_timedwait()
pthread_testcancel()
sem_wait()
sigwait()
...

pthread_setcancelstate

设置状态,有两种

  • PTHREAD_CANCEL_ENABLE (default)
  • PTHREAD_CANCEL_DISABLE
    Enable表示线程支持cancel

pthread_setcanceltype

  • PTHREAD_CANCEL_DEFERRED: 默认值,他不会马上结束,会在下一个cancelpoint结束
  • PTHREAD_CANCEL_ASYNCHRONOUS: 马上结束

pthread_cleanup_push & pthread_cleanup_pop

1
2
void pthread_cleanup_push(void (*routine)(void *), void *arg);
void pthread_cleanup_pop(int execute);

##Thread Safety

###对象构造

  • 不要在构造函数中注册毁掉
  • 不要过早的把this传给其他线程的对象

两段式构造,是个有效的解决方案

###对象析构
尽管我们会用互斥量来保证线程安全,但是还是难免会碰到如下情况

1
2
3
4
5
6
7
global shared_ptr<Job> ptr = make_shared<Job>()
Thread A
shared_ptr<Job> p1(ptr)
Thread B
ptr is going out of scope
  • 在这种情况下,直接使用互斥量就很难保证不会出问题,所以使用一个RAII构建的mutex是一个解决方法
1
2
3
4
MutexGuard lock(mtx)
//operate the ptr
..
..When it's going out of the scope, the lock object will continue to protect it until ptr destroyed

或者使用如下方法,p1和p2都是栈上对象,所以没有析构问题。

1
2
3
4
5
6
7
8
9
10
global shared_ptr<Job> ptr = make_shared<Job>()
Thread A
shared_ptr<Job> p1(ptr)
use p1 to operate object ptr pointed to
Thread B
shared_ptr<Job> p2(ptr)
use p2 to operate object
  • 另外一个解决方法是可以用另外一个线程专门管理这些对象的析构,相当于维护一个对象池
  • 或者考虑使用atomic来保护对象

###不要使用递归mutex

###每个对象保证自身的数据安全
对于数据的访问给予互斥量保护,这个时候要留心析构的问题,因为内部互斥量无法保证析构,如果两个线程同时在做析构(在使用shared_ptr的时候),那么会有双重释放的问题,一个符合RAII标准的mutexlock能够派上用场,因为他可以保护析构,在析构结束前lock不会析构。

###TCP作为进程间通信的方法
TCP是一个相对普适的方法来处理进程间通信,他甚至可以扩展到主机间通信,所以是个非常好的选择