java同步 静态变量的变化

wm124314 2019-12-24 07:37:29
public class abc implements Runnable{
//共享资源变量
static int count = 0;

@Override
public synchronized void run() {
for (int i = 0; i < 2; i++) {
count=count+1;
System.out.println(Thread.currentThread().getName()+":"+count);
}
}

public static void main(String[] args) throws InterruptedException {
abc syncTest1 = new abc();
abc syncTest2 = new abc();
Thread thread1 = new Thread(syncTest1,"thread1");
Thread thread2 = new Thread(syncTest2, "thread2");
thread1.start();
thread2.start();
}
}
某次结果:
thread1:1
thread2:2
thread2:4
thread1:3

无法理解最后两行
...全文
173 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
树成 2019-12-25
  • 打赏
  • 举报
回复
java有一个方式来解决楼主的问题 ,字段加上volatile static volatile int count = 0; 这样定义变量就不会出现楼主先4后3的问题。
qq_39936465 2019-12-25
  • 打赏
  • 举报
回复
引用 2 楼 炭木 的回复:
[quote=引用 1 楼 sj1231984 的回复:] 你的synchronized 方法是针对abc对象本身加锁的,你声明了俩个abc对象,那这俩个线程每人都有一个对象,也不会造成竞争啊,也就是你的synchronized 没啥用。。。。
这个我懂,程序本身并没有实现同步,但问题是count是静态变量,即使两个对象,两个线程应该使用的都是同一块内存区域,结果的倒数第二行count结果已经是4了,最后一行的结果怎么可能是3?无法理解这个[/quote] 你这里其实是2个独立线程,当一个线程取得count=3,另一个线程取得count=4时,会造成更早输出count=4的值,是因为线程输出count值时不会重新去确认当前共享的count变量,而是直接使用当前线程中保存count的值,所以你的线程是不安全的。共享变量在线程中需要加锁才会安全。
树成 2019-12-24
  • 打赏
  • 举报
回复
楼主这无法理解么?所谓的并行,并不是进入方法的并行,而是每个语句的并行,如果出现并行,无法保证线程都是按照规定顺序来执行的。你可以认为两个人赛跑,你可以理解一个人比另一个人快很多,一个人比另一个人晚起步,但是早越过终点,这是完全有可能的。
stacksoverflow 2019-12-24
  • 打赏
  • 举报
回复
引用 8 楼 炭木 的回复:
[quote=引用 5 楼 stacksoverflow 的回复:] thread1: thread2 count+1, - 算出参数1, - print(参数1), - - count+1, - 算出参数2, - print(参数2), count+1, - 算出参数3, - - count+1, - 算出参数4, - print(参数4) - print(参数3)
参数3和参数4都是各个线程独立内存里的数据?
引用 5 楼 stacksoverflow 的回复:
thread1: thread2 count+1, - 算出参数1, - print(参数1), - - count+1, - 算出参数2, - print(参数2), count+1, - 算出参数3, - - count+1, - 算出参数4, - print(参数4) - print(参数3)
参数3和参数4都是各自线程里独立内存里的数据?[/quote] 参数3,参数4是下面的代码编译后生成的局部变量,归各自线程的for循环block内所有。 Thread.currentThread().getName()+":"+count
wm124314 2019-12-24
  • 打赏
  • 举报
回复
引用 5 楼 stacksoverflow 的回复:
thread1: thread2 count+1, - 算出参数1, - print(参数1), - - count+1, - 算出参数2, - print(参数2), count+1, - 算出参数3, - - count+1, - 算出参数4, - print(参数4) - print(参数3)
参数3和参数4都是各个线程独立内存里的数据?
引用 5 楼 stacksoverflow 的回复:
thread1: thread2 count+1, - 算出参数1, - print(参数1), - - count+1, - 算出参数2, - print(参数2), count+1, - 算出参数3, - - count+1, - 算出参数4, - print(参数4) - print(参数3)
参数3和参数4都是各自线程里独立内存里的数据?
wm124314 2019-12-24
  • 打赏
  • 举报
回复
引用 3 楼 sj1231984 的回复:
[quote=引用 2 楼 炭木 的回复:][quote=引用 1 楼 sj1231984 的回复:] 你的synchronized 方法是针对abc对象本身加锁的,你声明了俩个abc对象,那这俩个线程每人都有一个对象,也不会造成竞争啊,也就是你的synchronized 没啥用。。。。
这个我懂,程序本身并没有实现同步,但问题是count是静态变量,即使两个对象,两个线程应该使用的都是同一块内存区域,结果的倒数第二行count结果已经是4了,最后一行的结果怎么可能是3?无法理解这个[/quote]这个是因为线程执行是先把共享内存里的数据拷贝一份副本到自己的内存中,每个线程都有自己的独立内存,执行完之后再把结果刷新到共享内存中。按这个思路想一下,你那个结果就不足为奇了。[/quote] 那println输出的是共享内存里的数据还是独立内存里的数据呀?
sunyiz 2019-12-24
  • 打赏
  • 举报
回复
其实问题出在 System.out.println
println 其实在输出时,会对 System.out 对象加锁
也就是说,在某一次执行中,
你的 thread1 虽然已经完成了 System.out.println 字符串参数的拼接,但是却让 thread2 先抢到了锁
所以反而是 thread2 的那一次打印先输出到了控制台
stacksoverflow 2019-12-24
  • 打赏
  • 举报
回复
thread1: thread2 count+1, - 算出参数1, - print(参数1), - - count+1, - 算出参数2, - print(参数2), count+1, - 算出参数3, - - count+1, - 算出参数4, - print(参数4) - print(参数3)
stacksoverflow 2019-12-24
  • 打赏
  • 举报
回复
thread1:count+1,算出参数1, print(参数1),-------------------count+1,算出参数3,----------------------------------print(参数3) thread2:---------------------count+1,算出参数2,print(参数2),-------------------count+1,算出参数4,print(参数4)----------------
海里的顽石 2019-12-24
  • 打赏
  • 举报
回复
引用 2 楼 炭木 的回复:
[quote=引用 1 楼 sj1231984 的回复:] 你的synchronized 方法是针对abc对象本身加锁的,你声明了俩个abc对象,那这俩个线程每人都有一个对象,也不会造成竞争啊,也就是你的synchronized 没啥用。。。。
这个我懂,程序本身并没有实现同步,但问题是count是静态变量,即使两个对象,两个线程应该使用的都是同一块内存区域,结果的倒数第二行count结果已经是4了,最后一行的结果怎么可能是3?无法理解这个[/quote]这个是因为线程执行是先把共享内存里的数据拷贝一份副本到自己的内存中,每个线程都有自己的独立内存,执行完之后再把结果刷新到共享内存中。按这个思路想一下,你那个结果就不足为奇了。
wm124314 2019-12-24
  • 打赏
  • 举报
回复
引用 1 楼 sj1231984 的回复:
你的synchronized 方法是针对abc对象本身加锁的,你声明了俩个abc对象,那这俩个线程每人都有一个对象,也不会造成竞争啊,也就是你的synchronized 没啥用。。。。
这个我懂,程序本身并没有实现同步,但问题是count是静态变量,即使两个对象,两个线程应该使用的都是同一块内存区域,结果的倒数第二行count结果已经是4了,最后一行的结果怎么可能是3?无法理解这个
海里的顽石 2019-12-24
  • 打赏
  • 举报
回复
你的synchronized 方法是针对abc对象本身加锁的,你声明了俩个abc对象,那这俩个线程每人都有一个对象,也不会造成竞争啊,也就是你的synchronized 没啥用。。。。

62,626

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧