linux编程主题之线程

来源:互联网 发布:仙剑奇侠传5剧情知乎 编辑:程序博客网 时间:2024/05/16 19:19

  每个线程有一个线程ID,线程ID只在它所属的进程环境中有效。可以使用函数来对两个线程ID进行比较:

      int pthread_equal(pthread_t tid1, pthread_t tid2);

  线程可以获取自身的线程ID:

      pthread_t pthread_self(void);

  线程创建:

      int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void*), void *restrict arg);

  线程退出:

      vod pthread_exit(void *rval_ptr);

        线程可以通过rval_ptr把自己的某些数据返回给其他需要这些数据的线程。

      int pthread_join(pthread_t thread, void **rval_ptr);

        线程可以通过rval_ptr访问别的线程传出来的数据。

  一个线程可以取消同一进程中的其他线程:

      int pthread_cancel(pthread_t tid);

  多线程编程一个很大的问题是如何解决线程间的互斥与同步,互斥量和条件变量是可以依赖的措施。

  1、互斥量

        互斥量是pthread的互斥接口,用来保护数据,确保同一时间只有一个线程访问数据。互斥量本质上是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。

        互斥量用pthread_mutex_t数据类型来表示,在使用互斥量之前,必须首先对它进行初始化,可以把它置为PTHREAD_MUTEX_INITIALIZER(用的不多),也可以通过函数初始化(用的多):

      int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

      int pthread_mutex_destroy(pthread_mutex_t *mutex);

        对互斥量进行加解锁:

      int pthread_mutex_lock(pthread_mutex_t *mutex);

      int pthread_mutex_unlock(pthread_mutex_t *mutex);

        线程加锁的过程中要注意死锁的现象:如果一个线程试图对同一个互斥量加锁两次,那么它自身就会陷入死锁状态;只有在一个线程试图以与另一个线程相反的顺序锁住互斥量时,才可能出现死锁。

        读写锁与互斥量类似,不过读写锁允许更高的并行性。读写锁有三种状态:读模式下加锁状态、写模式下加锁状态、不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它加锁的线程都可以得到访问权,但是如果线程希望以写模式对此锁进行加锁,它必须阻塞直到所有的线程释放读锁。虽然读写锁的实现各不相同,但当读写锁处于读模式锁住状态时,如果有另外的线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求。这样可以避免读模式锁长期占用,而等待的写模式锁请求一直得不到满足。读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的,当它以写模式锁住时,它是以独占模式锁住的。

        读写锁的初始化和销毁:

      int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);

      int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

        读写模式下的加锁与解锁:

      int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

      int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

      int pthread_rwlock_unlock(pthread rwlock_t *rwlock);

  2、条件变量

        条件变量是线程可用的另一种同步机制。条件变量给多个进程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定条件的条件发生。条件本身是由互斥量保护的。线程在改变条件状态之前必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁定互斥量以后才能计算条件。

        条件变量使用之前必须首先进行初始化,可以把它置为PTHREAD_COND_INITIALIZER(用的不多),也可以通过函数初始化(用的多):

      int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);

      int pthread_cond_destroy(pthread_cond_t *cond);

        等待条件变为真的函数:

      int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

          从pthread_cond_wait调用成功返回时,线程需要重新计算条件,因为其他的线程可能已经在运行并改变了条件。

        当线程条件已经满足,需要函数唤醒等待该条件的某个线程:

      int pthread_cond_signal(pthread_cond_t *cond);

          必须注意一定要在改变条件状态以后再给线程发送信号。

  线程私有数据的概念特别重要:每个线程可以独立地访问数据副本而不会受到其他线程的干扰。

    创建与数据进行关联的键的函数

      int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *));

        创建的键存放在keyp指向的内存单元,这个键可以被进程中的所有线程使用,但每个线程把这个键与不同的线程私有数据地址进行关联。

    取消键与线程私有数据之间的关联的函数

      int pthread_key_delete(pthread_key_t *key);

    保证多个线程只创建一个键,不会重复创建的函数

      pthread_once_t initflag=PTHREAD_ONCE_INIT;

      int pthread_once(pthread_once_t *initflag, void (*initfn)(void));

    设置和获取键对应的私有数据的函数

      void *pthread_getspecific(pthread_key_t key);

      int pthread_setspecific(pthread_key_t key, const void *value);

    设置线程信号屏蔽字的函数

      int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);

    线程等待信号发生的函数

      int sigwait(const sigset_t *restrict set, int *restrict signop);

    将信号发送到线程的函数

      int pthread_kill(pthread_t thread, int signo);