线程与进程的主要区别在于
线程同样由操作系统调度,面临竞争与死锁等问题。
一个简单的例子:
#include
#include
void *mythread(void *ptr)
{
std::cout << "Hello World\n";
return nullptr;
}
int main()
{
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, nullptr, mythread, nullptr);
pthread_create(&thread2, nullptr, mythread, nullptr);
pthread_join(thread1, nullptr);
pthread_join(thread2, nullptr);
}
用g++ scratchpad.cpp -lpthread命令编译,结果打印
thread id: 140609000044288
thread id: 140608991651584
用于创建线程的pthread_create()原型是
int pthread_create(
pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void*),
void *arg
);
用于等待线程执行结束的*pthread_join()*函数原型是
int pthread_join(
pthread_t thread,
void **value_ptr
);
第二个参数是返回值。
上面的例子面临几个问题:
POSIX规定线程要有ID用于识别,可以用*pthread_self()*查看。
一个带输入/输出的例子如下:
#include
#include
void *mythread(void *ptr)
{
(*reinterpret_cast<int*>(ptr))++;
return ptr;
}
int main()
{
int in_value = 42;
void *out_value = nullptr;
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, nullptr, mythread, &in_value);
pthread_create(&thread2, nullptr, mythread, &in_value);
pthread_join(thread1, &out_value);
pthread_join(thread2, &out_value);
std::cout << "value: " <<
*reinterpret_cast<int*>(out_value) << '\n'; // 44
}
这里两个线程操作的是同一个整型,同样由竞争的问题。
不及时退出的线程可能会消耗过多的CPU时间。
#include
#include
void *mythread(void *ptr)
{
while(true)
{
std::clog << static_cast<char*>(ptr) << '\n';
pthread_yield();
}
}
int main()
{
char name1[9] = "thread 1";
char name2[9] = "thread 2";
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, nullptr, mythread, name1);
pthread_create(&thread2, nullptr, mythread, name2);
pthread_join(thread1, nullptr);
pthread_join(thread2, nullptr);
}
上面的程序会不停地打印thread 1和thread 2,但两种打印的交替频率很快。这是pthread_yield()的作用,它允许当前线程释放对CPU的占用。如果不调用它,会发现thread 1重复打印很久才开始打印thread 2,并再次重复打印多次。
需要注意的是操作系统本身能够有效地调度线程,除非有很明确的目的,否则过度使用yileding反而会降低性能。而且这个函数并非在所有系统中都可用。
可以使用*sleep()*使线程进入休眠,用于调整性能和优化电池使用。
给出一个发生竞争的例子:
#include
#include
#include
int count = 0;
void *mythread(void *ptr)
{
count++;
}
int main()
{
while(true)
{
count = 0;
for(auto i =0; i < 1000; i++)
{
std::array<pthread_t, 8> threads;
for (auto &t : threads) {
pthread_create(&t, nullptr, mythread, nullptr);
}
for (auto &t : threads)
{
pthread_join(t, nullptr);
}
}
std::cout << "count: " << count << '\n';
}
}
上面的打印结果理论上应该是8000,但很多打印结果出现了7998、7999等,说明出现了对count全局变量的竞争。
用互斥量mutex解决:
#include
#include
#include
int count = 0;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *mythread(void *ptr)
{
pthread_mutex_lock(&lock);
count++;
pthread_mutex_unlock(&lock);
}
int main()
{
while(true)
{
count = 0;
for(auto i =0; i < 1000; i++)
{
std::array<pthread_t, 8> threads;
for (auto &t : threads) {
pthread_create(&t, nullptr, mythread, nullptr);
}
for (auto &t : threads)
{
pthread_join(t, nullptr);
}
}
std::cout << "count: " << cou