Linux Threading 线程
Linux Threading 线程
Freewheel 发表于10个月前
Linux Threading 线程
  • 发表于 10个月前
  • 阅读 50
  • 收藏 1
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

以下是单线程进程和多线程进程在内存方面的模型

即同一进程的线程之间共享一份代码,常量,全局变量和堆变量,但是有各自的本地变量(栈,寄存器)。

 

多线程与多进程的简单比较

数据共享方面:

进程之间无法访问对方的内存,因此需要通过kernel space创建共享对象进行沟通;

线程之间可以通过进程内的全局变量和堆变量进行沟通,更简单高效。(但同样需要解决race condition等同步问题)

 

POSIX thread library 标准线程库

 

pthread_create

int pthread_create( pthread_t *thread, 
                    const pthread_attr_t *attr, 
                    void *(*start_routine) (void *), 
                    void *arg 
                  );

线程的起始函数的参数和返回值都是 void* 类型,因此可以代入所有类型的指针。

传入线程的参数也是个指针,因此该参数的值在main thread 和 new thread 里都可以被更改。

 

pthread_exit

void pthread_exit(void *return_value);

 

pthread_join

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

 

Pthread Synchronization 线程层面的同步

除了使用semaphore,thread之间的同步还可以使用pthread_mutex 和 Condition Variable。

由于semaphore在使用上(编写代码)比较难,并且可读性比较差(因为功能太强大),更推荐后两者。

 

pthread_mutex 顾名思义专门用于作为互斥锁,通常在声明为全局变量,使用时十分简单

 pthread_mutex_lock(&mutex);
 // ... critical section
 pthread_mutex_unlock(&mutex);

与semaphore不同,pthread_mutex在被获取成功的时候,它就被该线程拥有了;而semaphore则没有被拥有这个概念,它只是在kernel space作为一个第三方的存在。

 

Condition Variable 名称较为歧义,其真实用法主要是通知 notification。

它内部没有变量,计数器等,调用 wait 和 signal 方法都是 atomical 和 stateless的。(优点:性能更好,更新变量是件麻烦的事情。)

signal 方法是无条件的,即任何wait的thread都会被唤醒。因此,wait代码附近常使用 while 循环,加入条件检查代码。

while ( meet_requirement()) {
  cond_wait(&v, &m);
}

 

为什么wait方法的第二个参数是一个pthread_mutex变量?

当thread因为wait进入挂起状态时,必须释放手上的锁,使得别的thread能获得锁并执行任务;

当thread从wait中被唤醒,就需要重新拿回锁。

示例代码:

mutex_lock(&m);
while (x!=y) {
  cond_wait(&v, &m);
}
printf(x/y = 1);
mutex_unlock(&m);

 

Reentrant可重入

reentrant 可重入函数 指即使线程在中途被打断并且从头调用也可以得到正确的答案,无论这个函数之前的调用是否完成。“if it can be interrupted in the middle of its execution, and then be safely called again ("re-entered") before its previous invocations complete execution.”

-- https://en.wikipedia.org/wiki/Reentrancy_(computing)

即可重入的函数不会使用全局变量和静态变量,所有的变量都只跟单次执行有关。因此,可重入函数有益于消除共享状态share state。

 

Thread safety  线程安全

线程安全是指在多线程的环境中能够避免race condition,并且保证数据同步。

实现线程安全的途径之一就是采用可重入的编程方法减少共享状态。

 

CPU atomic instructions

test_and_set() 

//pseudocode (indeed a single atomic instruction)
boolean test_and_set(boolean *target){
  boolean tmp = *target; //original value
  *target = 1; //set
  return tmp; //return the original value!
}

使用 test_and_set 实现 mutex (示例代码,并非真实实现)

局限性: test_and_set 只能同步2个线程(进程)

 

compare_and_swap()

//pseudocode (indeed a single atomic instruction)
int compare_and_swap(int *value, int expected, int new_value) {
    int temp = *value; //original value
    if (*value == expected)
      *value = new_value;
    
    return temp; //return the original value
}

使用compare_and_swap实现mutex (示例代码,并非真实实现)

现在compare_and_swap在底层被大量用来实现semaphores, mutex, lock-free operations

 

几个编程概念

Lock-free programming

Lock-free DSA ensures a high throughput of a system/operation by 
- Guarantee progress for some threads when there are multiple threads 保证部分线程进展
- While any particular thread is blocked/waiting, some other threads must be running in order to make sure all the cores are doing useful work without stalls 保证CPU一直运行,做有用功

名字稍有歧义,Lock-free与实现中是否用到锁无关

 

Wait-free programming

Wait-free DSA ensures a high throughput of a system/operation by
– Guarantee progress for every thread when there are multiple threads without sacrificing latency of a particular thread ( Sometimes impossible to achieve) 保证所有线程都有进展
– Thread1.operation X() must finish in a finite number of steps,regardless of the state/speed of the other thread  保证一个线程操作在有限时间内一定完成

 

 

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 8
博文 77
码字总数 47525
×
Freewheel
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: