锁定老帖子 主题:多线程开发,表示很凌乱
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-04-17
junlas 写道
第一次做网络应用的一个项目的服务器端,以前一直都是ssh开发,tomcat服务器,也做过很长时间的客户端从没考虑过多线程的问题,现在不做web项目、也不纯客户端开发了,忽然觉得头大。
说说主要困惑,举个例子来说,我总是会想到这个类实例化以后的这个对象,在同一时间可能会被N多客户端请求,那么我担心这种并发会导致我当前对象中的数据交错,一不是一,二也不是二了,所以,有种恨不得每个方法都是synchronized的,但是很明显这样做,是不对的。当然,以前也学习过多线程的基础,网上的资料也没少看、少找,但是还是不能完全切透这种模式的思路。 楼主还没有理解“线程安全”的含义,线程本身不存在什么安全不安全的问题,主要体现在一个线程在执行某个方法时,对这个类内部的属性变量访问的安全与否。拿servlet来说,为什么说他不安全,是指在servlet中对定义的类变量访问不安全。
所以楼主只要理解了这句话,就会明白,只有可修改的类变量才有线程安全问题(如只读的常量也不存在线程安全问题),对于方法中传入的参数或其他声明的临时变量,根本不存在线程安全问题。
类变量线程安全又分2种情况, 第一种是单例,如果一个类的实例是单例的,所有线程都访问相同的实例,那么这个类的类变量不是线程安全的,因为一个线程对这个实例的类变量任何操作,都会影响到其他线程。 第二种是多例,如果在不同线程方法中,创建了对象,那么这2个对象由各自线程管理,互不干扰,也不存在线程安全问题。
|
|
返回顶楼 | |
发表时间:2012-04-17
spyker 写道 去看一本书
Java并发编程实践 好的,这本书我这周就去买来 |
|
返回顶楼 | |
发表时间:2012-04-17
最后修改:2012-04-17
zfc827 写道
junlas 写道
第一次做网络应用的一个项目的服务器端,以前一直都是ssh开发,tomcat服务器,也做过很长时间的客户端从没考虑过多线程的问题,现在不做web项目、也不纯客户端开发了,忽然觉得头大。
说说主要困惑,举个例子来说,我总是会想到这个类实例化以后的这个对象,在同一时间可能会被N多客户端请求,那么我担心这种并发会导致我当前对象中的数据交错,一不是一,二也不是二了,所以,有种恨不得每个方法都是synchronized的,但是很明显这样做,是不对的。当然,以前也学习过多线程的基础,网上的资料也没少看、少找,但是还是不能完全切透这种模式的思路。 楼主还没有理解“线程安全”的含义,线程本身不存在什么安全不安全的问题,主要体现在一个线程在执行某个方法时,对这个类内部的属性变量访问的安全与否。拿servlet来说,为什么说他不安全,是指在servlet中对定义的类变量访问不安全。
所以楼主只要理解了这句话,就会明白,只有可修改的类变量才有线程安全问题(如只读的常量也不存在线程安全问题),对于方法中传入的参数或其他声明的临时变量,根本不存在线程安全问题。
类变量线程安全又分2种情况, 第一种是单例,如果一个类的实例是单例的,所有线程都访问相同的实例,那么这个类的类变量不是线程安全的,因为一个线程对这个实例的类变量任何操作,都会影响到其他线程。 第二种是多例,如果在不同线程方法中,创建了对象,那么这2个对象由各自线程管理,互不干扰,也不存在线程安全问题。
嗯,非常感谢回复这么多,还是可以理解的。我把我的一个疑惑描述一下,可能有点2。有一种这样的情况,唯一的一个共享数据对象O,内部有方法A,方法B,起了5个线程去执行方法A,起了另外3个线程执行方法B,好的,请教,在方法A、B中: 1.访问对象O中的普通类变量需要synchronized,如果不是普通类变量,是java.util.concurrent包下的类型变量,就不用synchronized了,这点没错吧,如果没错,我理解的应该就没错。正如你上面所说。 2.方法A、B中的参数、临时变量,是否也需要synchronized?这是比较疑惑的了,我发帖的主要原因。我的理解是:线程1可能正执行到方法A、B的一半时,被切到线程2来执行这个方法,因为参数和临时变量没synchronized,这个值就变了??
我觉得是我肯定理解错了?求指点,如何理解呢 |
|
返回顶楼 | |
发表时间:2012-04-17
2.方法A、B中的参数、临时变量,是否也需要synchronized?
看来你对线程的理解还没入门。每个线程都有自己的线程栈,方法传入参数、临时变量都会在线程栈中,线程切换过程,线程栈也会随着切换 |
|
返回顶楼 | |
发表时间:2012-04-17
[quote="junlas"]
[quote="zfc827"] [quote="junlas"] 第一次做网络应用的一个项目的服务器端,以前一直都是ssh开发,tomcat服务器,也做过很长时间的客户端从没考虑过多线程的问题,现在不做web项目、也不纯客户端开发了,忽然觉得头大。 说说主要困惑,举个例子来说,我总是会想到这个类实例化以后的这个对象,在同一时间可能会被N多客户端请求,那么我担心这种并发会导致我当前对象中的数据交错,一不是一,二也不是二了,所以,有种恨不得每个方法都是synchronized的,但是很明显这样做,是不对的。当然,以前也学习过多线程的基础,网上的资料也没少看、少找,但是还是不能完全切透这种模式的思路。 楼主还没有理解“线程安全”的含义,线程本身不存在什么安全不安全的问题,主要体现在一个线程在执行某个方法时,对这个类内部的属性变量访问的安全与否。拿servlet来说,为什么说他不安全,是指在servlet中对定义的类变量访问不安全。 所以楼主只要理解了这句话,就会明白,只有可修改的类变量才有线程安全问题(如只读的常量也不存在线程安全问题),对于方法中传入的参数或其他声明的临时变量,根本不存在线程安全问题。 类变量线程安全又分2种情况, 第一种是单例,如果一个类的实例是单例的,所有线程都访问相同的实例,那么这个类的类变量不是线程安全的,因为一个线程对这个实例的类变量任何操作,都会影响到其他线程。 第二种是多例,如果在不同线程方法中,创建了对象,那么这2个对象由各自线程管理,互不干扰,也不存在线程安全问题。 嗯,非常感谢回复这么多,还是可以理解的。我把我的一个疑惑描述一下,可能有点2。有一种这样的情况,唯一的一个共享数据对象O,内部有方法A,方法B,起了5个线程去执行方法A,起了另外3个线程执行方法B,好的,请教,在方法A、B中: 1.访问对象O中的普通类变量需要synchronized,如果不是普通类变量,是java.util.concurrent包下的类型变量,就不用synchronized了,这点没错吧,如果没错,我理解的应该就没错。正如你上面所说。 2.方法A、B中的参数、临时变量,是否也需要synchronized?这是比较疑惑的了,我发帖的主要原因。我的理解是:线程1可能正执行到方法A、B的一半时,被切到线程2来执行这个方法,因为参数和临时变量没synchronized,这个值就变了?? 我觉得是我肯定理解错了?求指点,如何理解呢 方法中的临时变量不是多线程共享的,因此不需要同步,这是每个方法私有的。说道参数,要看这个参数是不是对象,是对象的话,这个对象有没有被多个线程共享,如果共享了,那就要同步住这个对象所涉及的所有方法:sychronized(对象)。 说白了,无非一句话,被共享的变量被多个线程改变时,就要同步。 |
|
返回顶楼 | |
发表时间:2012-04-18
有2个方法操纵一个map对象,怎么实现线程安全?
2个方法都加上锁? |
|
返回顶楼 | |
发表时间:2012-04-18
schweigen 写道 2.方法A、B中的参数、临时变量,是否也需要synchronized?
看来你对线程的理解还没入门。每个线程都有自己的线程栈,方法传入参数、临时变量都会在线程栈中,线程切换过程,线程栈也会随着切换 受益良多啊。谢谢。 |
|
返回顶楼 | |
发表时间:2012-04-18
837062099 写道 [quote="junlas"]
[quote="zfc827"] [quote="junlas"] 第一次做网络应用的一个项目的服务器端,以前一直都是ssh开发,tomcat服务器,也做过很长时间的客户端从没考虑过多线程的问题,现在不做web项目、也不纯客户端开发了,忽然觉得头大。 说说主要困惑,举个例子来说,我总是会想到这个类实例化以后的这个对象,在同一时间可能会被N多客户端请求,那么我担心这种并发会导致我当前对象中的数据交错,一不是一,二也不是二了,所以,有种恨不得每个方法都是synchronized的,但是很明显这样做,是不对的。当然,以前也学习过多线程的基础,网上的资料也没少看、少找,但是还是不能完全切透这种模式的思路。 楼主还没有理解“线程安全”的含义,线程本身不存在什么安全不安全的问题,主要体现在一个线程在执行某个方法时,对这个类内部的属性变量访问的安全与否。拿servlet来说,为什么说他不安全,是指在servlet中对定义的类变量访问不安全。 所以楼主只要理解了这句话,就会明白,只有可修改的类变量才有线程安全问题(如只读的常量也不存在线程安全问题),对于方法中传入的参数或其他声明的临时变量,根本不存在线程安全问题。 类变量线程安全又分2种情况, 第一种是单例,如果一个类的实例是单例的,所有线程都访问相同的实例,那么这个类的类变量不是线程安全的,因为一个线程对这个实例的类变量任何操作,都会影响到其他线程。 第二种是多例,如果在不同线程方法中,创建了对象,那么这2个对象由各自线程管理,互不干扰,也不存在线程安全问题。 嗯,非常感谢回复这么多,还是可以理解的。我把我的一个疑惑描述一下,可能有点2。有一种这样的情况,唯一的一个共享数据对象O,内部有方法A,方法B,起了5个线程去执行方法A,起了另外3个线程执行方法B,好的,请教,在方法A、B中: 1.访问对象O中的普通类变量需要synchronized,如果不是普通类变量,是java.util.concurrent包下的类型变量,就不用synchronized了,这点没错吧,如果没错,我理解的应该就没错。正如你上面所说。 2.方法A、B中的参数、临时变量,是否也需要synchronized?这是比较疑惑的了,我发帖的主要原因。我的理解是:线程1可能正执行到方法A、B的一半时,被切到线程2来执行这个方法,因为参数和临时变量没synchronized,这个值就变了?? 我觉得是我肯定理解错了?求指点,如何理解呢 方法中的临时变量不是多线程共享的,因此不需要同步,这是每个方法私有的。说道参数,要看这个参数是不是对象,是对象的话,这个对象有没有被多个线程共享,如果共享了,那就要同步住这个对象所涉及的所有方法:sychronized(对象)。 说白了,无非一句话,被共享的变量被多个线程改变时,就要同步。 了解。。 |
|
返回顶楼 | |
发表时间:2012-04-18
aa87963014 写道 有2个方法操纵一个map对象,怎么实现线程安全?
2个方法都加上锁? 一般我都是用ConcurentHashMap这个对象 |
|
返回顶楼 | |
发表时间:2012-04-18
队列,LZ你只要深刻理解掌握队列,那么写多线程的话就绰绰有余了。
只要结构设计得合理,把操作都序列成action,那么很多地方都不必加锁。 举个例子,比如A和B都同时访问某个数据,那么你只要把A和B的请求都封装成action,丢进队列里,那么,数据根本不必加锁,队列加锁就行。说到底这就是异步的思想。 抛开多核cpu不讲,就以前的单核,其实线程也只不过是分片执行的模拟而已。在系统内核,阻塞其实就是CPU空转,所以无论你怎么模拟同步,最终还是单个“线程”在跑而已。所以异步架构更适合现在PC架构,即便现在多核CPU,采用异步也能大大减少锁带来的热点。 从我们大多数应用场景来看,CPU并不是瓶颈,IO才是。所以我很推崇NODEJS的那一套,简洁明了。 |
|
返回顶楼 | |