`

Integer不能作为synchronized的对象吗

 
阅读更多

 

public class SychronizedTest implements Runnable {
	
	private Timer t = new Timer();

	public static void main(String[] args) {
		
		SychronizedTest st = new SychronizedTest();

		Thread thread1 = new Thread(st, "Thread1");
		Thread thread2 = new Thread(st, "Thread2");

		thread1.start();
		thread2.start();
	}

	public void run() {
		this.t.add();
	}
}

class Timer {
	private Integer i = 0;
	
	private Object o = new Object();

	public void add() {
		//i 没有被2个线程竞争,2个线程都可以获得对i的锁,但是如果换成o,则一个线程等待一个线程阻塞
		//synchronized (o) {
		synchronized (i) {
			this.i++;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("您是第" + this.i + "个使用i的线程," + Thread.currentThread().getName());

		}
	}
}

 //i 没有被2个线程竞争,2个线程都可以获得对i的锁,但是如果换成o,则一个线程等待一个线程阻塞

 

有点奇怪,换成atmoicinteger也是可以的,观察线程栈也可以说明这一点

 

"Thread2" prio=6 tid=0x17122400 nid=0x1d18 at breakpoint[0x172df000]
   java.lang.Thread.State: RUNNABLE
	at com.google.prophet.quickstart.basic.thread.Timer.add(SychronizedTest.java:34)
	- locked <0x02fb05c8> (a java.lang.Integer)
	at com.google.prophet.quickstart.basic.thread.SychronizedTest.run(SychronizedTest.java:19)
	at java.lang.Thread.run(Thread.java:662)

   Locked ownable synchronizers:
	- None

"Thread1" prio=6 tid=0x17121800 nid=0x18b8 at breakpoint[0x1728f000]
   java.lang.Thread.State: RUNNABLE
	at com.google.prophet.quickstart.basic.thread.Timer.add(SychronizedTest.java:34)
	- locked <0x02fb05f8> (a java.lang.Integer)
	at com.google.prophet.quickstart.basic.thread.SychronizedTest.run(SychronizedTest.java:19)
	at java.lang.Thread.run(Thread.java:662)

   Locked ownable synchronizers:
	- None
 

 

0x02fb05f8
0x02fb05c8

  Integer是一个对象但是id却不同,可能这个Integer各自在2个线程的工作内存中,而不是共享内存中,目前我只能这么解释,而Object,或者是AtomicInteger则是创建在了共享内存中,所以可以进行同步。

 

分享到:
评论

相关推荐

    【05-面向对象(下)】

    •但对引用类型的变量而言,它仅仅保存的是一个引用,final只能保证他的地址不变,但不能保证对象,所以引用 类型完全可以改变他的对象。 可执行“宏替换”的final变量 •对一个final变量来说,不管它...

    超级有影响力霸气的Java面试题大全文档

     声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,...

    JAVA面试题最全集

    修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被...

    java 面试题 总结

    声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其...

    java面试题

    答:String是不可变的对象,每次对String类型进行改变都相当于产生了一个新的对象,StringBuffer是可变的字符序列,所以如果要经常改变某个字符串的话建议使用StringBuffer。 list、set、map问题? 答:set 不允许...

    关于JAVA面试的100题及其答案

    java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类 3、int 和 Integer 有什么区别 Java 提供两种不同的类型:引用类型和原始类型(或内置...

    进销存系统文档作业例子

    声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其...

    java经典面试2010集锦100题(不看你后悔)

    B) 可以为抽象类定义对象,但是不能为接口定义对象。 C) 抽象类与接口的用法几乎都相同,具体用哪一个方法,只是在于程序设计人员的编程习惯而已。 D) 在Java中,最多使用的是抽象类,因为应用抽象类也可以实现多...

    sesvc.exe 阿萨德

    因此通常建议能提前预估 HashMap 的大小最好,尽量的减少扩容带来的性能损耗。 根据代码可以看到其实真正存放数据的是 transient Entry,V&gt;[] table = (Entry,V&gt;[]) EMPTY_TABLE; 这个数组,那么它又是如何定义的...

    Java 2实用教程(第三版)实验指导与习题解答

    System.out.printf("\n%d不在1至99999之间",number); } } } 实验3 猜数字游戏 2.模板代码 GuessNumber.java import javax.swing.JOptionPane; public class GuessNumber { public static void main (String...

    达内 coreJava 习题答案

    (1)若某个年份能被4整除但不能被100整除,则是闰年。 (2)若某个年份能被400整除,则也是闰年。 import java.util.Scanner; class Bissextile{ public static void main(String[] arge){ System.out.print(...

Global site tag (gtag.js) - Google Analytics