日期:2014-05-20  浏览次数:20585 次

synchroized方法和类的区别
请问哪位大神能解释一下,synchronized修饰方法和作为块的区别呢?例如以下代码:

 public class Counter {
 
  public static Integer count = 0;
 
  public static void inc() {
 
  //这里延迟1毫秒,使得结果明显
  try {
  Thread.sleep(30);
  } catch (InterruptedException e) {
  }
  //注意看这里。监控count了。
  synchronized(count){
  count++;
  System.out.println(count);
  }
  }
 
  public static void main(String[] args) {
 
  //同时启动1000个线程,去进行i++计算,看看实际结果
  for (int i = 0; i < 1000; i++) {
  new Thread(new Runnable() {
  @Override
  public void run() {
  Counter.inc();
  }
  }).start();
  }
 
  //这里每次运行的值都有可能不同,可能为1000
  System.out.println("运行结果:Counter.count=" + Counter.count);
  }
}

为什么synchronized作为块的时候得出的结果可能不是1000,而如果改为修饰方法inc时结果却可以正确,为1000呢?

------解决方案--------------------
public synchronized static void inc()
应该是你这个方法的原因吧,它是静态方法,线程锁的是Counter 的CLASS对象,而不是Counter 的对象。
你循环1000次 就是调用Counter 的CLASS对象的inc方法1000次。
------解决方案--------------------
synchronized锁定的是实例块,但是你的count是static的对象,并且你的方法也是static的方法,所以你用实例锁去锁class对象根本没用的!!!所以你需要把synchronized放到方法上锁定static方法,也就是锁的class对象了。如果你需要用synchronized块的话,需要把方法改成非静态方法
------解决方案--------------------
package com.djk.thread;

public class Counter 
{

//首先你以前来锁这个对象是错的 他是会变的
public static Integer count =0;

//现在我给你重弄一把锁,这把锁是静态的保证只有一个对象是同一把锁
private static Object object = new Object();

//这里要改成非静态的 你也可以再这里加synchronized 效果也是1000,主要线程中都是同一个对象调用这个方法
public void inc()
{

//这里延迟1毫秒,使得结果明显
try
{
Thread.sleep(30);
}
catch (InterruptedException e) 
{

}
//这里不要锁count是没用的,锁object 最后执行的结构是1000
synchronized(object)
{
count++;
System.out.println(count);
}
}
public static void main(String[] args)
{
//同时启动1000个线程,去进行i++计算,看看实际结果
//这边这样定义是为了保证线程中时同一个对象调用方法
final Counter c = new Counter();
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
@Override
public void run()
{
c.inc();
}
}).start();
}

//这里每次运行的值都有可能不同,可能为1000
//还有这里是没必要写的,看这个是看不出结果的,这句话是主线程的,主线程不一定是在最后执行,可能在你生成线程的时候就执行了
System.out.println("运行结果:Counter.count=" + Counter.count);
}
}

lz你参考下这是我按照你代码改的加的批准