多线程中并发问题

原创 2016年08月28日 21:12:50

我在写多线程的例子的时候,由于机子的原因遇到了并发性问题,于是在stack overflow 发了帖子,通过和国外的一些程序员的交流过程中对并发多线程的理解更深了,下面是我发的问题和在问题解决过程中和他们的讨论,希望可以和大家一起学习,有什么不清楚的可以直接联系我相互讨论。

得到的结论是一般并发多线程都是用Cocurrentmap类这种线程安全的类型而非hashmap这种线程不安全的map。至于原因请看我们的讨论过程:

When i use cycle sentence to run two Threads it shows me that problem:java.lang.Thread.run(Thread.java:745) but i figure it out use two methods:\first if i dont run the application just debug it and use breakpoint it would be ok . second based on my demo just has two threads so i could copy this part of code "

    new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int data = new Random().nextInt();
                        System.out.println(Thread.currentThread().getName()
                                + " has put data:" + data);
                        threadDataMap.put(Thread.currentThread(), data);
                        new A().get();
                        new B().get();
                    }
                }).start();

"

for twice it would also be ok .

all my demo code is below:

    package 多线程;

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;

    public class ThreadScopShareData {

    private static int data = 0;
    private static Map<Thread,Integer> threadDataMap=new HashMap<Thread,Integer>();
    public static void main(String[] args) {
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    int data = new Random().nextInt();
                    System.out.println(Thread.currentThread().getName()
                            + " has put data:" + data);
                    threadDataMap.put(Thread.currentThread(), data);
                    new A().get();
                    new B().get();
                }
            }).start();
        }
    }

    static class A {
        public void get() {
            int data=threadDataMap.get(Thread.currentThread());
            System.out.println("A from " + Thread.currentThread().getName()
                    + "get data:" + data);
        }
    }

    static class B {
        public void get() {
            int data=threadDataMap.get(Thread.currentThread());
            System.out.println("B from " + Thread.currentThread().getName()
                    + "get data:" + data);
        }
    }
    }

and the right result should be like below: Thread-1 has put data :-1188249922 Thread-0 has put data :1024718434 A from Thread-0 get data :1024718434 B from Thread-0 get data :1024718434 A from Thread-1 get data :-1188249922 B from Thread-1 get data :-1188249922

but the bug is below:Thread-1 has put data :-807205084 Thread-0 has put data :-976943511 A from Thread-0 get data :-976943511

   Exception in thread "Thread-1" B from Thread-0 get data :-976943511
    java.lang.NullPointerException
    at 多线程.ThreadScopeShareData$A.get(ThreadScopeShareData.java:33)
    at 多线程.ThreadScopeShareData$1.run(ThreadScopeShareData.java:22)
    at java.lang.Thread.run(Thread.java:745)

As far as i know the Thread-1 would totally change and kill the thread-0 so it would appear a nullPointerException . but i am not sure.

shareeditdeleteflag
 
 
 
Not clean in which cases you are not getting the expected result – ravthiru Aug 25 at 3:57
 
i meant :if i run this demo it would except a NullPointerException . but i based on my current code , i have two solutions .First is use "debug" command and put some breakpoint in it rather than "run" command . second, if i copy the thread part code for twice rather than use cycle sentence. it would be ok. but i dont know why the Thread was messed up . – qiaopan Ma Aug 25 at 13:05  

Since you use threadDataMap in multiple threads use ConcurrentHashMap instead of HashMap.

shareedit
 
 
 
thank u very much .and u r right if i use ConcurrentHashMap it would be ok, but could u tell me why it would be messed up if i use just HashMap . – qiaopan Ma 2 days ago  
 
The cause is in concurrent changing of HashMap internal state. – Konstantin Labun 2 days ago
 
Most likely it is the result of concurrent initiation: when thread-1 and thread-0 at same time call put() on empty map, each of them start to create it's own hash-table and since Thread-0 was second to finish this action, it overwritten already created hash-table by Thread-1. So when you try to get data by key 'Thread-1' it returns null. – Konstantin Labun 2 days ago
 
i understand now the possible reason. but i am confused with the sequence during i debug the code below,the order is first i =0 then create a new Thread instance , then go to start() method, after that i= 1 create another new Thread instance then go to start method . after both finished , it goes to the run() method. : for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { } }).start();} – qiaopan Ma 2 days ago  
 
i think the sequence maybe should be like this : after i=0 , it create a new Thread instance then , just go to start() and go to run() method. after this , i=1 , it create another new Thread instance then go to its start() method and go to this run() method. and when i copy this code:new Thread(new runnable(){@override public void run(){}}).start(); twice , the sequence is like what i described . and maybe that is the reason. I really want to know why if i use "for" cycle the run order would be like that . – qiaopan Ma 2 days ago  

You have to understand that this static method Thread.currentThread()Returns a reference to the currently executing thread object.

So if you execute it the first time it is going to return the main thread, which is the main class, before event spawning the thread number 1.Java Doc for Thread.currentThread()

You should use the Thread.setName(String name) to explicitely set the names of threads.

You cant use Thread.currentThread() static method because it will always refer to the main running thread and not your new spawned threads.

Try this.

    import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThreadScopShareData {

private static int data = 0;
private static Map<Thread,Integer> threadDataMap=new HashMap<Thread,Integer>();
public static void main(String[] args) {
    for (int i = 0; i < 2; i++) {
      Thread t =  new Thread(new Runnable() {
            @Override
            public void run() {
                int data = new Random().nextInt();
                System.out.println(Thread.currentThread().getName()
                        + " has put data:" + data);
                threadDataMap.put(Thread.currentThread(), data);
                new A().get();
                new B().get();
            }
        });
       t.setName(i);
       t.start();
    }
}
shareedit
 
 
I don't think your analysis is right. The run() method is indeed called by 2 threads and not by 'main' thread. The code that he wrote in question is correct but as it was messed up by hashmap since it wasn't handled the way he expected, he got wrong output. But regardless, I don't think it's due to the reason you gave above, IMHO – Sanjeev Dhiman Aug 25 at 6:13
 
thank both of u . but i am afraid Sanjeev Dhiman is right . i tried to run Two threads rather than one . so based on this . could u find any clues about my question. – qiaopan Ma 2 days ago                                                                                           

版权声明:本文为博主原创文章,若要转载请注明出处!^_^

【数据一致性】多线程写数据库,如何保持数据一致性?

如题,这种情况一般在数字类数据更新时需要保证万无一失,尤其是金额类的数字 比如小明的银行号有1000块钱 他做了一笔交易20元,很简单,我们要做一次更新 UPDATE XXX SET MONEY=NO...
  • chiweitree
  • chiweitree
  • 2015年11月06日 16:09
  • 2716

关于java中并发时引起的问题(多线程问题)

场景如下: 我有一个订单导入页面,如下图: 公司里面有很多员工,都需要进入这个页面,进行订单导入。 并发进行,可能存在这样的问题,两个同事,同时输了一个相同的订单号,同时点击订单...
  • u010523770
  • u010523770
  • 2016年06月24日 19:09
  • 764

传说中的并发编程ABA问题

什么是ABA问题 ABA并不是一个缩写,更像是一个形象的描述。ABA问题出现在多线程或多进程计算环境中。 首先描述ABA。假设两个线程T1和T2访问同一个变量V,当T1访问变量V时,读取到...
  • u012813201
  • u012813201
  • 2017年06月02日 10:17
  • 555

java多线程_并发问题的解析

首先看一下java中的多线程 1.多线程是合理充分利用了CPU,内存资源 。 2.多个线程同步操作一个加锁对象,效率是得不到提升的,记得在一个博客上看的一篇日志,将一个加锁的对象比喻成一个卫生间,同一...
  • liunian02050328
  • liunian02050328
  • 2015年03月23日 17:39
  • 1474

在Android中使用并发来提高速度和性能

在Android中使用并发来提高速度和性能 Android框架提供了很实用的异步处理类。然而它们中的大多数在一个单一的后台线程中排队。当你需要多个线程时你是怎么做的? 众所周知,UI更新发生在U...
  • wangjigaoyi
  • wangjigaoyi
  • 2016年07月15日 09:16
  • 8027

Java 多线程 BlockingQueue 实现 高并发邮件 代码 MailBean

/**  *   */ package com.pingan.emall.biz.util; import java.io.Serializable; import java...
  • lisu_suby
  • lisu_suby
  • 2014年10月27日 16:04
  • 754

Java 多线程并发解决方案

Java 多线程并发编程会有许多不同的问题,主要有如下问题的应用: 多线程读写共享数据同步问题并发读数据,保持各个线程读取到的数据一致性的问题。 解决方案: sync...
  • langjian2012
  • langjian2012
  • 2015年03月22日 22:08
  • 4990

redis多个线程操作单个key场景的并发问题

redis是单线程的, 出并发问题只可能是逻辑上有漏洞, 比如先取再写 , 可以采用某种方式规避 比如multi /exec 事务  比如 Redis 事务 Redis Exec 命令用...
  • AlbertFly
  • AlbertFly
  • 2016年10月18日 10:00
  • 7267

关于多线程处理数据并发问题处理

数据量多时需要要多线程处理,尤其在集群环境下很可能发生资源竞争的情况,此时就需要谨慎的对数据加锁,如果加锁出了问题,也是个麻烦事。 为安全考虑,一般处理这种问题有几个步骤: 为此个业务加开关,如果...
  • u012186154
  • u012186154
  • 2017年09月05日 15:14
  • 251

并发危险:解决多线程代码中的 11 个常见的问题

转自:http://msdn.microsoft.com/zh-cn/magazine/cc817398.aspx
  • mergerly
  • mergerly
  • 2014年09月03日 16:00
  • 2950
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:多线程中并发问题
举报原因:
原因补充:

(最多只允许输入30个字)