- 问题引出
附上代码
public class Test01 {
private boolean flag = false;
public void refresh() {
flag = true;
}
public void load() {
while (!flag) {
}
System.out.println("out");
}
public static void main(String[] args) throws InterruptedException {
Test01 test01 = new Test01();
new Thread(test01::load).start();
Thread.sleep(3000L);
new Thread(test01::refresh).start();
}
}
两个线程,一个线程A等待flag变量变为false,另一个线程B在睡眠三秒后修改flag为false,按道理这个线程A应该停止,毕竟flag的值变为了false。但是出现了两个奇怪的现象:
1、当开启MIXED混合编译的时候停不下来
2、当开启XINT解释模式时可以停下来
3、当在中间加入了Synchronized代码块后可以停下来
- 我们从c语言的角度看看结果如何:
#include<stdio.h>
#include<pthread.h>
int flag = 0;
int count = 1;
void *modify(void *arg) {
printf("modify start!\n");
flag = 1;
printf("modify end!\n");
pthread_exit((void *) 0);
};
void *sum(void *arg) {
printf("sum start!\n");
while (!flag) {
count++;
}
printf("sum end!\tcount = %d\n", count);
pthread_exit((void *) 0);
};
int main() {
pthread_t modifyPid;
pthread_t sumPid;
if ((pthread_create(&sumPid, NULL, sum, NULL)) != 0) {
printf("pthread_create err\n");
return -1;
}
if ((pthread_create(&modifyPid, NULL, modify, NULL)) != 0) {
printf("pthread_create err\n");
return -1;
}
if (pthread_join(modifyPid, NULL) != 0) {
printf("pthread_join err\n");
return -1;
}
if (pthread_join(sumPid, NULL) != 0) {
printf("pthread_join err\n");
return -1;
}
}
结果:
sum start!
modify start!
modify end!
sum end! count = 14341
结果竟然停下来了。。。什么鬼!
先别激动, 先看看我的编译命令
gcc test.c -lpthread
来, 我们加点料
gcc -O4 test.c -lpthread
结果:
sum start!
modify start!
modify end!
哎呀! 停不下来了。
一言不合上汇编, 我们看看编译器都做了些什么
gcc -S test.c -lpthread
modify: // modify的代码段
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movl $.LC0, %edi
call puts
movl $1, flag(%rip) // 将1放入flag的内存地址中,然后退出
movl $.LC1, %edi
call puts
movl $0, %edi
call pthread_exit
......
sum: // sum的代码段
.LFB3:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movl $.LC2, %edi
call puts
jmp .L3
.L4:
movl count(%rip), %eax
addl $1, %eax
movl %eax, count(%rip)
.L3:
movl flag(%rip), %eax
testl %eax, %eax
je .L4
movl count(%rip), %eax
movl %eax, %esi
movl $.LC3, %edi
movl $0, %eax
call printf
movl $0, %edi
call pthread_exit
.cfi_endproc
.LFE3:
.size sum, .-sum
.section .rodata
.LC4:
.string "pthread_create err"
.LC5:
.string "pthread_join err"
.text
.globl main
.type main, @function
modify:
.LFB14:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $.LC0, %edi
call puts
movl $.LC1, %edi
movl $1, flag(%rip)
call puts
xorl %edi, %edi
call pthread_exit
.cfi_endproc
.LFE14:
.size modify, .-modify
.section .rodata.str1.1
.LC2:
.string "sum start!"
.LC3:
.string "sum end!\tcount = %d\n"
.text
.p2align 4,,15
.globl sum
.type sum, @function
sum:
.LFB15:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $.LC2, %edi
call puts
movl flag(%rip), %eax
testl %eax, %eax
jne .L9
.L6:
jmp .L6 // 死循环
.L9:
movl count(%rip), %esi
movl $.LC3, %edi
xorl %eax, %eax
call printf
xorl %edi, %edi
call pthread_exit
.cfi_endproc
.LFE15:
.size sum, .-sum
.section .rodata.str1.1
.LC4:
.string "pthread_create err"
.LC5:
.string "pthread_join err"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
待续。。。。。。