JAVA中,关于多线程的疑惑,求解答
JAVA中,关于多线程的疑惑
疑惑来源于网上文章的阅读,和自己的测试
来源于网上的测试代码
public class Runnable1 implements Runnable{
private static int count = 0;
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Runnable1());
thread.start();
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("result: " + count);
}
@Override
public void run() {
synchronized (this){
for (int i = 0; i < 10000; i++) {
count++;
}
}
}
}
描述
该文章是一个描述synchronized关键字的文章,文章说对于count这个共享变量,以synchronized来锁住当前对象保证并发访问的原子性,但是也让我产生了疑惑,为什么一定要访问本类中的变量,如果线程访问一个普通的类,比如user(举例而已)这样的java bean对象,由于java bean中的属性都是私有的,那么只能通过get/set方法访问,那么如果我锁住的是该bean的class对象是否可以保证,并发访问的正确性呢?
我做了测试,代码如下
public class Test {
private static int value = 0;
public static int getValue() {
return value;
}
public static void setValue(int value) {
Test.value = value;
}
public static void main(String[] args) {
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("threadPool-%d").build();
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10),
factory, new ThreadPoolExecutor.AbortPolicy());
poolExecutor.execute(new Thread1());
poolExecutor.execute(new Thread1());
poolExecutor.execute(new Thread1());
poolExecutor.execute(new Thread1());
poolExecutor.execute(new Thread1());
poolExecutor.shutdown();
System.out.println(value);
}
}
public class Thread1 extends Thread{
@Override
public void run() {
synchronized (Thread.class){
for (int i = 0; i < 100; i++) {
int value = Test.getValue();
++value;
Test.setValue(value);
}
}
}
}
描述以及之后的修改
按照一样的思路,这里我修饰的是Test.class对象,测试结果不一致
之后尝试将bean的get/set方法也使用synchronized修饰,发现得到的结果依然不一致
开始怀疑自己的理解有问题
难道sychronized不是将访问的线程都自进入该对象时就加上锁吗???
求指点,万分感谢
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
锁一个全局变量并没有问题, 问题是
线程都还没执行完呢,你直接把它干掉了,输出能对么
后面这段代码?哪里加锁了?
synchronized的目的是保证代码块的原子性操作
应该是两方面原因:
第一:你显式的使用了shutdown(),此时线程可能还在跑你就给干掉了,当然预期结果不一样
第二:即使不使用shutdown,你提交线程之后马上进行了System.out.println(value);此时预期结果也不一样,因为提交线程之后是异步去跑的,所以此时的主线程(就是这个main方法)不会等待之前的线程是否跑完就会直接进行输出了。所以预期结果不一样。
你可以再看看上面的demo代码,它有一个Thread.sleep(500),然后再输出;其实这个主线程等500ms的目的就是让子线程能够跑完,然后输出。假如demo代码的线程500ms跑不完,他的value结果也是不对的。你可以修改demo代码如下:主要修改是在run方法中加了Thread.sleep(1),保证这个线程在500ms跑不完。
综上你把你的main代码修改如下看看,变动点有2个: