java 线程同步的问题,为什么有时不能用synchronized(){}同步块命令

例如:publicclassMyThreadimplementsRunnable{privateintticket=100;publicvoidrun(){//synch... 例如:
public class MyThread implements Runnable {

private int ticket=100;
public void run(){
//synchronized(ticket){ 为什么不用这个同步块命令
while(ticket>0){
System.out.println(ticket--+" is saled by "+Thread.currentThread().getName());
}
//}

}

public static void main(String[] args) {
MyThread m=new MyThread();
Thread t1=new Thread(m,"Window 1");
Thread t2=new Thread(m,"Window 2");
Thread t3=new Thread(m,"Window 3");
t1.start();
t2.start();
t3.start();
}
}

为什么第四行的地方不用加synchronized(){}这样的命令!!!!难道不存在线程争用ticket的问题吗?
展开
 我来答
anglewang98
推荐于2016-05-14 · TA获得超过535个赞
知道小有建树答主
回答量:420
采纳率:80%
帮助的人:279万
展开全部

把private int ticket=100;(基本数据类型)

修改为private Integer ticket=100;就行了。(包装类)


int是java中的基本数据类型,基本数据类型不允许使用synchronized,都会报 xxx is not a valid type's argument for the synchronized statement,这个可能跟基础数据类型的存储类型有关,以下资料可以参考

1.java程序运行时有6种地方存储数据,分别是:寄存器、栈、堆、静态存储、常量存储、
非RAM(随机存储器),主要是堆与栈的存储。
2.堆与栈是java用来在RAM中存储数据的地方,java自动管理堆和栈,程序员不能直接设置堆和栈。
3.栈的优势是:存取速度比堆要快,仅次于直接位于cpu中的寄存器;栈数据可以共享。   
但缺点是:存在栈中数据大小与生命周期必须是确定的,缺乏灵活性。
4.堆的优势在于可以动态分配内存大小,生存期也不必事先告诉编译器,java的垃圾收集器会
自动收走这些不再使用的数据,缺点是由于要在运行时动态分配内存,存取速度较慢。
5.基本数据类型的存储,java的基本数据类型共有8种:int,short,byte,long,float,double,
boolean,(基本数据类型中并没有String的基本类型)。这种类型如int=3的形式来定义,
称为自动变量。自动变量存在的是字面值,即不是类的实例,也不是类的引用。a 是一个指向
int类型的引用,指向3这个字面值。这些字面值的数据由于大小可知,生存期可知
(这些字面值固定定义在某个程序块里面,程序块退了,字段值就消失了),
处于追求速度的原因就存在栈中。
6.另外栈有一个很重要的特殊性,就是存在栈中的数据可以共享。
如 需要定义int a = 3; int b =3;这两个自动变量。编译器先处理int  a=3;
首先在栈中创建一个变量为a的引用,然后查找栈有没有字面值为3的引用,没有找到,
就开辟一个存放3这个字面值的地址,然后将a指向3的地址。
接着处理int b=3;在创建完b这个引用变量后,由于在栈中已经有了3这个字面值,
即将b直接指向3的地址。这样,就出现了a和b同事指向3的情况。 
定义完a与b后,在令a=4,那么b不会等于4,而是等于3,。
在编译器内部,遇到时,它就会中新搜索栈中是否有4这个字面值,如果没有,
重新开辟地址存放4的值。如果已经有就直接将a指向这个地址,因此a的值改变不会影响b的值。
7.对象的内存模型.创建一个对象包括对象的声明和实例化两步:
声明对象的引用和对象的实例化。声明一个对象引用时,将在栈内存为对象的引用变量分配空间
;对象实例化是,在堆内存中为类成员变量分配内存,并将其初始化为各数据类型默认值,
接着进行显示初始化,最后调用构造方法为成员变量赋值,返回堆内存中对象的引用
(相当于首地址)给应用变量,通过引用变量来引用堆内存中的对象。
8.包装类数据的存储:基本数据类型的定义都是直接在栈中,如果是包装类型来创建对象,
就和普通对象一样。
9.string数据类型是一种特殊数据类型,既可以用基本数据类型格式来创建,
也可以用普通基本类型来创建。
追问
你说的我知道,
即使改成Integer 我还是问同样的问题,为什么不需要要加synchronized(ticket
){} 也就是为什么不加这个也能得出正确的结果??
追答

int是基础数据类型,基础数据类型都是保存在栈中的,栈数据可以共享。所以不需要加synchronized。

测试过之后应该是改成。private Integer ticket= new Integer(100);

不加synchronized运行结果类似:

100 is saled by Window 1
100 is saled by Window 3
库霞雰8g
2019-04-04
知道答主
回答量:5
采纳率:0%
帮助的人:1.9万
展开全部
对象锁,私有锁方式中,ticket必须是对象,且不能是int、long等基本类型,也不能是基本类型的包装类。原因是Java的自动封箱和解箱操作在作怪。这里的ticket--实际上是ticket = new Integer(ticket-1),所以执行完ticket--后,ticket已经不是原来的对象了,同步块自然就无效了
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
QQMSD8
推荐于2017-10-18 · 知道合伙人软件行家
QQMSD8
知道合伙人软件行家
采纳数:6788 获赞数:13239
没有做不到,只有想不到,帮助别人的同时也是对自己的提升

向TA提问 私信TA
展开全部
你那个加了也没有意义,因为你把synchronized加在线程的代码上了

你的线程却new了很多个,并没有线程争用
追问
怎么没有线程争用?new了很多个,但是都共享一个ticket啊!不信你运行下试试??
追答
你的ticket 是线程自己的,如果你声明成static就不一样了
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
天涯路口南方人
2017-10-18
知道答主
回答量:3
采纳率:0%
帮助的人:2716
展开全部
存在对CPU的争夺,不过最后打印出错误信息只是概率很低,可以在共享数据里加一个sleep,就一定会出现打印出的值里出现-1 -2 0 这样的
可以这样测试:
public class MyThread implements Runnable {

private int ticket=100;
public void run(){
//synchronized(ticket){ 为什么不用这个同步块命令
while(ticket>0){
try{Thread.sleep(10);}catch(Exception e){}//处理异常的处理方式,让线程在执行时休眠
System.out.println(ticket--+" is saled by "+Thread.currentThread().getName());
}
//}

}

public static void main(String[] args) {
MyThread m=new MyThread();
Thread t1=new Thread(m,"Window 1");
Thread t2=new Thread(m,"Window 2");
Thread t3=new Thread(m,"Window 3");
t1.start();
t2.start();
t3.start();
}
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
塔咖备号
2019-06-11
知道答主
回答量:1
采纳率:0%
帮助的人:722
展开全部
看书的时候有一句话挺好的,我们应该解决错误而不是降低错误的发生概率。
虽然是几年前的问题,但是解答里面就一个说中了,其他都不知道在说些什么,或许是我段位太低了吧。
你sleep一下当前线程就会发现错误了。

while (ticket > 0) {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(ticket-- + " is saled by " + Thread.currentThread().getName());
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(3)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式