demo
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
using namespace std;
long int a = 0;
pthread_mutex_t mutex;
pthread_mutex_t mutex2;
void* threadFunc(void *arg)
{
// pthread_mutex_lock(&mutex);
for(int i = 0; i < 500000; i++)
{
a = a+1;
}
// pthread_mutex_unlock(&mutex);
// pthread_mutex_lock(&mutex2);
}
void* threadFunc2(void *arg)
{
// pthread_mutex_lock(&mutex2);
for(int i = 500000; i < 1000000; i++)
{
a = a+1;
}
// pthread_mutex_unlock(&mutex2);
// pthread_mutex_lock(&mutex);
}
int main(int argc,char **argv)
{
pthread_t thread1,thread2;
// pthread_create(&thread1 ,NULL, threadFunc,NULL);
pthread_create(&thread1, NULL, threadFunc, NULL);
pthread_create(&thread2 ,NULL, threadFunc2,NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
cout << "value a = " << a << endl;
return 0;
}
1 多线程编译及调试
# 1 编译生成带符号信息的程序
g++ multhread.cpp -g -lpthread -o test_thread# 2 开始调试程序
gdb ./test_thread
# 3 显示源程序
layout next
此时会显示如下:
输入下面的命令 “r”继续运行程序
屏幕显示错乱,可在gdb命令下输入refresh刷新。
# 刷新屏幕并给函数增加断点
(gdb) refresh
(gdb) b threadFunc
Breakpoint 1 at 0x4009de: file multhread.cpp, line 16.
(gdb) b threadFunc2
Breakpoint 2 at 0x400a11: file multhread.cpp, line 27.
此时代码中有断点的位置显示“b+”
输入如下命令运行程序:
(gdb) r
Starting program: /home/ren/Desktop/test/test02/test_thread
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff6f4e700 (LWP 36510)]
[New Thread 0x7ffff674d700 (LWP 36511)]
[Switching to Thread 0x7ffff6f4e700 (LWP 36510)]
Thread 2 "test_thread" hit Breakpoint 1, threadFunc (arg=0x0) at multhread.cpp:16
# 查看线程信息
(gdb) info threads
Id Target Id Frame
1 Thread 0x7ffff7fb5740 (LWP 36507) "test_thread" clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:81
* 2 Thread 0x7ffff6f4e700 (LWP 36510) "test_thread" threadFunc (arg=0x0) at multhread.cpp:16
3 Thread 0x7ffff674d700 (LWP 36511) "test_thread" threadFunc2 (arg=0x0) at multhread.cpp:27
# 调试线程2
(gdb) thread 2
[Switching to thread 2 (Thread 0x7ffff6f4e700 (LWP 36510))]
#0 threadFunc (arg=0x0) at multhread.cpp:16
#查看堆栈调用信息(可以看到线程创建过程 clone -> start_thread )
(gdb) where
#0 threadFunc (arg=0x0) at multhread.cpp:16
#1 0x00007ffff7bc16ba in start_thread (arg=0x7ffff6f4e700) at pthread_create.c:333
#2 0x00007ffff757551d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) watch a
Hardware watchpoint 4: a
#不断输入c发现a的值不是连续变化的,说明有其他线程在修改a
(gdb) c
Continuing.
Thread 3 "test_thread" hit Hardware watchpoint 3: a
Old value = 4
New value = 6
Thread 3 "test_thread" hit Hardware watchpoint 4: a
Old value = 4
New value = 6
threadFunc2 (arg=0x0) at multhread.cpp:27
# 观察所有线程a的变化
(gdb) thread apply all watch a
Thread 3 (Thread 0x7ffff674d700 (LWP 36511)):
Hardware watchpoint 5: a
Thread 2 (Thread 0x7ffff6f4e700 (LWP 36510)):
Hardware watchpoint 6: a
Thread 1 (Thread 0x7ffff7fb5740 (LWP 36507)):
Hardware watchpoint 7: a
(gdb) 8 in /home/ren/Desktop/test/test02/multhread.cpp
#反复输入c观察所有线程的变量a的变化,发现每个线程中a变化都不是连续的
(gdb) c
Continuing.
[Switching to Thread 0x7ffff674d700 (LWP 36511)]
Thread 3 "test_thread" hit Hardware watchpoint 3: a
Old value = 18
New value = 19
Thread 3 "test_thread" hit Hardware watchpoint 4: a
Old value = 18
New value = 19
Thread 3 "test_thread" hit Hardware watchpoint 5: a
2 典型的死锁调试
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
using namespace std;
long int a = 0;
pthread_mutex_t mutex;
pthread_mutex_t mutex2;
void* threadFunc(void *arg)
{
pthread_mutex_lock(&mutex);
for(int i = 0; i < 5000; i++)
{
a = a+1;
sleep(2);
}
pthread_mutex_lock(&mutex2);
cout<<"threadFunc value a = "<<a<<endl;
pthread_mutex_unlock(&mutex);
pthread_mutex_unlock(&mutex2);
}
void* threadFunc2(void *arg)
{
pthread_mutex_lock(&mutex2);
for(int i = 5000; i < 10000; i++)
{
a = a+1;
sleep(2);
}
pthread_mutex_lock(&mutex);
cout<<"threadFunc2 value a = "<<a<<endl;
pthread_mutex_unlock(&mutex);
pthread_mutex_unlock(&mutex2);
}
int main(int argc,char **argv)
{
pthread_t thread1,thread2;
// pthread_create(&thread1 ,NULL, threadFunc,NULL);
pthread_create(&thread1, NULL, threadFunc, NULL);
pthread_create(&thread2 ,NULL, threadFunc2,NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
cout << "value a = " << a << endl;
return 0;
}
编译及调试
g++ multhread2.cpp -g -lpthread -o test_thread2
gdb ./test_thread2
进入gdb调试
(gdb) r
Starting program: /home/ren/Desktop/test/test02/test_thread2
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff6f4e700 (LWP 38558)]
[New Thread 0x7ffff674d700 (LWP 38559)]
^C
Thread 1 "test_thread2" received signal SIGINT, Interrupt.
0x00007ffff7bc298d in pthread_join (threadid=140737336633088, thread_return=0x0) at pthread_join.c:90
90 pthread_join.c: No such file or directory.
(gdb) info threads
Id Target Id Frame
* 1 Thread 0x7ffff7fb5740 (LWP 38554) "test_thread2" 0x00007ffff7bc298d in pthread_join (threadid=140737336633088,
thread_return=0x0) at pthread_join.c:90
2 Thread 0x7ffff6f4e700 (LWP 38558) "test_thread2" 0x00007ffff753a38d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
3 Thread 0x7ffff674d700 (LWP 38559) "test_thread2" 0x00007ffff753a38d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
(gdb) thread 3
[Switching to thread 3 (Thread 0x7ffff674d700 (LWP 38559))]
#0 0x00007ffff753a38d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
84 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0 0x00007ffff753a38d in nanosleep () at ../sysdeps/unix/syscall-template.S:84#1 0x00007ffff753a2da in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#2 0x0000000000400ba6 in threadFunc2 (arg=0x0) at multhread2.cpp:33
#3 0x00007ffff7bc16ba in start_thread (arg=0x7ffff674d700) at pthread_create.c:333
#4 0x00007ffff757551d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) thread 2
[Switching to thread 2 (Thread 0x7ffff6f4e700 (LWP 38558))]
#0 0x00007ffff753a38d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
84 in ../sysdeps/unix/syscall-template.S
(gdb) bt
#0 0x00007ffff753a38d in nanosleep () at ../sysdeps/unix/syscall-template.S:84#1 0x00007ffff753a2da in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#2 0x0000000000400b09 in threadFunc (arg=0x0) at multhread2.cpp:19
#3 0x00007ffff7bc16ba in start_thread (arg=0x7ffff6f4e700) at pthread_create.c:333
#4 0x00007ffff757551d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
#以下命令会让所有线程都执行这个命令,比如命令为bt,查看所有线程的具体的栈信息,常用(gdb) thread apply all bt
Thread 3 (Thread 0x7ffff6fee700 (LWP 39888)):
#0 0x00007ffff78bc38d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
#1 0x00007ffff78bc2da in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#2 0x00000000004008a3 in threadFunc2 (arg=0x0) at multhread2.c:30
#3 0x00007ffff7bc16ba in start_thread (arg=0x7ffff6fee700) at pthread_create.c:333
#4 0x00007ffff78f751d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
Thread 2 (Thread 0x7ffff77ef700 (LWP 39887)):
#0 0x00007ffff78bc38d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
#1 0x00007ffff78bc2da in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#2 0x0000000000400821 in threadFunc (arg=0x0) at multhread2.c:16
#3 0x00007ffff7bc16ba in start_thread (arg=0x7ffff77ef700) at pthread_create.c:333
#4 0x00007ffff78f751d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
Thread 1 (Thread 0x7ffff7fb7700 (LWP 39883)):
#0 0x00007ffff7bc298d in pthread_join (threadid=140737345681152, thread_return=0x0) at pthread_join.c:90
#1 0x000000000040094f in main (argc=1, argv=0x7fffffffd9f8) at multhread2.c:46
thread apply all bt 很有用
解决方法:
加锁顺序要相同,先拿到锁的后释放锁