关闭

多线程中并发问题

标签: 多线程线程安全并发安全
260人阅读 评论(1) 收藏 举报
分类:

我在写多线程的例子的时候,由于机子的原因遇到了并发性问题,于是在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                                                                                           

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:161659次
    • 积分:5258
    • 等级:
    • 排名:第5395名
    • 原创:171篇
    • 转载:26篇
    • 译文:0篇
    • 评论:1359条
    Q我吧
    有什么要跟我说的么,请点击这里哦
    博客专栏
    最新评论