2个线程,1个打印字母A-Z,另一个打印1-26 要求交替打印 A1B2C3...Z26
代码结构:
* main.c
//
// 2个线程,1个打印字母A-Z,另一个打印1-26 要求交替打印 A1B2C3...Z26
//
#include
#include
#ifndef NULL
#define NULL (void *)0
#endif
#ifndef bool
typedef int bool;
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
typedef void *(*start_routine_t)(void *);
pthread_mutex_t print_mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t print_cv = PTHREAD_COND_INITIALIZER;
volatile bool should_alpha = true; /* should print alphabets? */
void *print_alphabets(void *param) {
int n = 26;
int c = 0x41;
while (n-- > 0) {
pthread_mutex_lock(&print_mtx);
while (!should_alpha) {
pthread_cond_wait(&print_cv, &print_mtx);
}
fputc(c++, stdout);
should_alpha = false;
pthread_mutex_unlock(&print_mtx);
pthread_cond_signal(&print_cv);
}
return NULL;
}
void *print_digits(void *param) {
int c;
for (c = 1; c < 27; c++) {
pthread_mutex_lock(&print_mtx);
while (should_alpha) {
pthread_cond_wait(&print_cv, &print_mtx);
}
fprintf(stdout, "%d", c);
should_alpha = true;
pthread_mutex_unlock(&print_mtx);
pthread_cond_signal(&print_cv);
}
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t t1, t2;
pthread_create(&t1, NULL, print_alphabets, NULL);
pthread_create(&t2, NULL, print_digits, NULL);
pthread_join(t1, 0);
pthread_join(t2, 0);
fputc(0x0a, stdout);
return 0;
}
* CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(thread_sync)
set(CMAKE_C_STANDARD 99)
link_libraries("pthread")
add_executable(thread_sync main.c)
Build:
====================[ Build | thread_sync | Debug ]============================= C:\Windows\system32\wsl.exe --distribution Ubuntu --exec /bin/bash -c "export CLION_IDE=TRUE && export CLICOLOR_FORCE=1 && export TERM=xterm && export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' && export JETBRAINS_IDE=TRUE && cd /mnt/e/CLionProjects/thread_sync/cmake-build-debug && /usr/bin/cmake --build /mnt/e/CLionProjects/thread_sync/cmake-build-debug --target thread_sync -- -j 6" [100%] Built target thread_sync Build finished
Run:
C:\Windows\system32\wsl.exe --distribution Ubuntu --exec /bin/bash -c "cd /mnt/e/CLionProjects/thread_sync/cmake-build-debug && /mnt/e/CLionProjects/thread_sync/cmake-build-debug/thread_sync"
A1B2C3D4E5F6G7H8I9J10K11L12M13N14O15P16Q17R18S19T20U21V22W23X24Y25Z26
Process finished with exit code 0
用全局变量global不好,在实际项目中容易出错。改成参数传给线程routine
//
// 2个线程,1个打印字母A-Z,另一个打印1-26 要求交替打印 A1B2C3...Z26
//
#include
#include
typedef struct {
pthread_mutex_t mtx;
pthread_cond_t cv;
volatile int alpha;
} print_t;
void *print_alphabets(void *param) {
int n = 26;
int c = 0x41;
print_t *p = (print_t *)param;
while (n-- > 0) {
pthread_mutex_lock(&p->mtx);
while (!p->alpha) {
pthread_cond_wait(&p->cv, &p->mtx);
}
fputc(c++, stdout);
p->alpha = 0;
pthread_mutex_unlock(&p->mtx);
pthread_cond_signal(&p->cv);
}
return NULL;
}
void *print_digits(void *param) {
int c;
print_t *p = (print_t *)param;
for (c = 1; c < 27; c++) {
pthread_mutex_lock(&p->mtx);
while (p->alpha) {
pthread_cond_wait(&p->cv, &p->mtx);
}
fprintf(stdout, "%d", c);
p->alpha = 1;
pthread_mutex_unlock(&p->mtx);
pthread_cond_signal(&p->cv);
}
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t t1, t2;
print_t p = {
.mtx = PTHREAD_MUTEX_INITIALIZER,
.cv = PTHREAD_COND_INITIALIZER,
.alpha = 1 /* should print alphabets? */
};
pthread_create(&t1, NULL, print_alphabets, &p);
pthread_create(&t2, NULL, print_digits, &p);
pthread_join(t1, 0);
pthread_join(t2, 0);
fputc(0x0a, stdout);
return 0;
}
注意, mutex, cond必须要初始化,否则阻塞不动。
mutex的lock, unlock范围尽可能小。先unlock再signal或者broadcast
多线程代码里不能用sleep,因为不知道要等几秒。什么时候该等待、什么时候该继续往下走。
sleep可以被signal打断
void bcl_udelay( long usec) {
struct timeval timeout;
timeout.tv_usec = usec % 1000000;
timeout.tv_sec = usec / 1000000;
select(1, NULL, NULL, NULL, &timeout);
}
可以用select系统调用实现一个
/* According to POSIX.1-2001, POSIX.1-2008 */
#include
/* According to earlier standards */
#include
#include
#include
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
#include
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask);