代码如下:
package testOther;import java.util.HashMap;public class TestMig { /**
 * @param args
 */
public static void main(String[] args) {
new TestMig();
} public static HashMap<String, String> map = new HashMap<String, String>(); public TestMig() {
myThreadClass1 thread1 = new myThreadClass1();
myThreadClass2 thread2 = new myThreadClass2();
Thread t1 = new Thread(thread1);
Thread t2 = new Thread(thread2);
t1.start();
t2.start();
} class myThreadClass1 implements Runnable { public void run() { synchronized (map) {
System.out.println("start" + Thread.currentThread().getName());
System.out.println(Thread.currentThread().getName() + " "
+ map.hashCode());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("end" + Thread.currentThread().getName());
}
}
} class myThreadClass2 implements Runnable {
public void run() {
System.out.println("start" + Thread.currentThread().getName());
System.out.println(Thread.currentThread().getName() + " "
+ map.hashCode());
map.put("1", "haha");
System.out.println("end" + Thread.currentThread().getName());
}
}}问题:这个问题是根据刚才有个网友的问题变化而来,我的map是个静态变量,就是说两个线程应该是共享同一个map的,为什么线程1对map加锁后仍然不能阻止线程2对map的操作?谢谢!

解决方案 »

  1.   

    个人理解:同步是说同一时刻只能有一个线程访问,又没规定是哪个线程访问,你Thread.sleep(10000)就已经把线程t1给停止了,这时t2当然就可以用了,但同一时刻始终是只有一个线程在访问map,要么t1要么t2
      

  2.   

    Thread.sleep(10000)是在synchronized块中,另外在线程1  sleep 之前,线程2的信息已经打出来了
      

  3.   

    我电脑上是这个结果:
    startThread-0
    Thread-0 0
    startThread-1
    Thread-1 0
    endThread-1
    endThread-0你的呢
      

  4.   


    我把sleep改了,换成会影响时间的代码:
    package testOther;import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;public class TestMig { /**
     * @param args
     */
    public static void main(String[] args) {
    new TestMig();
    } public static HashMap<String, String> map = new HashMap<String, String>(); public TestMig() {
    myThreadClass1 thread1 = new myThreadClass1();
    myThreadClass2 thread2 = new myThreadClass2();
    Thread t1 = new Thread(thread1);
    Thread t2 = new Thread(thread2);
    t1.start();
    t2.start();
    } class myThreadClass1 implements Runnable { public void run() { synchronized (map) {
    System.out.println("start" + Thread.currentThread().getName());
    System.out.println(Thread.currentThread().getName() + " "
    + map.hashCode());
    // try {
    // Thread.sleep(10000);
    // } catch (InterruptedException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    for (int i = 0; i < 10; i++) {
    File file = new File("d:\\" + i + ".txt");
    if (!file.exists()) {
    try {
    file.createNewFile();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    } System.out.println("end" + Thread.currentThread().getName());
    }
    }
    } class myThreadClass2 implements Runnable {
    public void run() {
    System.out.println("start" + Thread.currentThread().getName());
    System.out.println(Thread.currentThread().getName() + " "
    + map.hashCode());
    map.put("1", "haha");
    System.out.println("end" + Thread.currentThread().getName());
    }
    }}结果:
    startThread-0
    Thread-0 0
    startThread-1
    Thread-1 0
    endThread-1
    endThread-0即在1线程结束之前,就是synchronized块中,2线程仍然访问了map
      

  5.   

    对synchronized理解有误
    myThreadClass2 里面map的访问没有同步,可以随便访问的
      

  6.   


    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;public class TestMig {    /**
         * @param args
         */
        public static void main(String[] args) {
            new TestMig();
        }    public static HashMap<String, String> map = new HashMap<String, String>();    public TestMig() {
            myThreadClass1 thread1 = new myThreadClass1();
            myThreadClass2 thread2 = new myThreadClass2();
            Thread t1 = new Thread(thread1);
            Thread t2 = new Thread(thread2);
            t1.start();
            t2.start();
        }    class myThreadClass1 implements Runnable {        public void run() {            synchronized (map) {
                    System.out.println("start" + Thread.currentThread().getName());
                    System.out.println(Thread.currentThread().getName() + " "
                            + map.hashCode());
                    // try {
                    // Thread.sleep(10000);
                    // } catch (InterruptedException e) {
                    // // TODO Auto-generated catch block
                    // e.printStackTrace();
                    // }
                    for (int i = 0; i < 10; i++) {
                        File file = new File("d:\\" + i + ".txt");
                        if (!file.exists()) {
                            try {
                                file.createNewFile();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }                System.out.println("end" + Thread.currentThread().getName());
                }
            }
        }    class myThreadClass2 implements Runnable {
            public void run() {
                System.out.println("start" + Thread.currentThread().getName());
                System.out.println(Thread.currentThread().getName() + " "
                        + map.hashCode());
                map.put("1", "haha");
                System.out.println(map.size());
                System.out.println("end" + Thread.currentThread().getName());
            }
        }}你把map的大小打印出来
    我的结果是:
    startThread-0
    Thread-0 0
    endThread-0
    startThread-1
    Thread-1 0
    1
    endThread-1
    map是在线程0操作完后才被put,至于你的程序结果
    startThread-0 
    Thread-0 0 
    startThread-1 
    Thread-1 0    //个人理解,我线程也不熟,打印出map的hashcode不能算访问了map吧
    endThread-1 
    endThread-0 
      

  7.   


    map是静态共享对象,myThreadClass2 和myThreadClass1 引用的是同一个map
      

  8.   


    打印出map的hashCode是访问了map的hashcode方法,怎么能不算访问map -_-!
      

  9.   

    那就要看你这个访问是怎么理解的了,同步是防止同一时刻被多个线程访问,其原因是怕多个线程同时对同步对象进行修改,这个hashcode不是属于这个范围吧,它是固定的,而put则是要对其的内容进行修改了
      

  10.   


    对一个变量加锁,所有该变量的操作都是原子性的。另外,endThread-0 是在2线程操作完了map以后才打出来的
      

  11.   

    我根本就不认为那是对map的操作,所以说endThread-0最后出来也不影响我的结论,当然,我可能是错的,等高手来说说吧
      

  12.   

    你将synchronized 的代码提出来做一个函数,两个线程都调用这个函数,试一下。
      

  13.   

    Map 不是同步的,可以试一下,HashTable 它是同步的。
     synchronized (map)  我想LZ这里只是在这个类里同步了,但class myThreadClass1 无关。
      

  14.   

    你上边那个线程加了synchronized(map),表示获得了map锁才能进入同步块,并不是这里锁了其他地方就不能访问你下边那个线程并没有尝试去获得对map的锁,所以可以随便访问了
      

  15.   


    你的意思是synchronized不是对map加锁?只是表示得到锁?有点晕,那加锁是什么?
      

  16.   


    import java.util.*;public class Test {    /**
         * @param args
         */
        public static void main(String[] args) {
            new Test();
        }
        //加锁方法
        public static Map map = Collections.synchronizedMap(new HashMap<String, String>());    public Test() {
            myThreadClass1 thread1 = new myThreadClass1();
            myThreadClass2 thread2 = new myThreadClass2();
            Thread t1 = new Thread(thread1);
            Thread t2 = new Thread(thread2);
            t1.start();
            t2.start();
        }    class myThreadClass1 implements Runnable {        public void run() {            
                    System.out.println("start" + Thread.currentThread().getName());
                    
                    //开始锁定
                    System.out.println(Thread.currentThread().getName() + " "
                            + map.hashCode());
                    try {
                     //暂停10秒
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println("end" + Thread.currentThread().getName());
                
            }
        }    class myThreadClass2 implements Runnable {
            public void run() {
                System.out.println("start" + Thread.currentThread().getName());
                
                //开始锁定
                System.out.println(Thread.currentThread().getName() + " "
                        + map.hashCode());
                map.put("1", "haha");
                System.out.println("end" + Thread.currentThread().getName());
            }
        }}
      

  17.   

    1首先我没有找到你的map
    2因为线程2对map操作不需要得到map的锁线程加锁并不代表不能访问被加锁对象,而是另外一个对象不能得到这个对象的锁,即有且只有一个线程能够得到这个锁