在看zwchen很久之前的一篇博客,地址如下
http://zwchen.iteye.com/blog/91088
做了个测试,按照第一种做法
为使用synchronized,并未出现 线程共享情况,(我使用的是tomcat6.0带的servlet包)数据都是
SimpleServlet@c4fe76 ==> Thread[http-8080-1,5,main]:
Counter = 60
Counter = 61
Counter = 62
Counter = 63
Counter = 64
Counter = 65
Counter = 66
Counter = 67
Counter = 68
Counter = 69
SimpleServlet@c4fe76 ==> Thread[http-8080-1,5,main]:
Counter = 70
Counter = 71
Counter = 72
Counter = 73
Counter = 74
Counter = 75
Counter = 76
Counter = 77
Counter = 78
Counter = 79
SimpleServlet@c4fe76 ==> Thread[http-8080-1,5,main]:
Counter = 80
Counter = 81
Counter = 82
Counter = 83
Counter = 84
Counter = 85
Counter = 86
Counter = 87
Counter = 88
Counter = 89
正常输出。 请问各位高手,这个是为什么??
还有,其中的
synchronized (mutex) 为什么要用mutex这个参数?
我认为synchronized的参数是表明同步的是哪块,所以我改成 我自己servlet中的req,也可以正常跑
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
synchronized (req)
另外 ,最关键的:Thread.sleep((long) Math.random() * 1000);
我改成Thread.sleep(1000);,输出的结果就好像是线程共享了??
SimpleServlet@64883c ==> Thread[http-8080-3,5,main]:
Counter = 4
Counter = 6
Counter = 10
Counter = 14
Counter = 18
Counter = 22
Counter = 26
Counter = 30
Counter = 34
Counter = 38
SimpleServlet@64883c ==> Thread[http-8080-6,5,main]:
Counter = 4
Counter = 7
Counter = 11
Counter = 15
Counter = 19
Counter = 23
Counter = 27
Counter = 31
Counter = 35
Counter = 39
SimpleServlet@64883c ==> Thread[http-8080-7,5,main]:
Counter = 4
Counter = 8
Counter = 12
Counter = 16
Counter = 20
Counter = 24
Counter = 28
Counter = 32
Counter = 36
Counter = 40
下面附上 ZWCHEN先生的原文,并对他表示深深的敬意,谢谢!
然后,我们通过一个html页面向该servlet发出三次请求:
刷新页面几次后,产生的结果为:
com.zwchen.servlet.SimpleServlet@11e1bbf ==> Thread[http-8081-Processor23,5,main]:
Counter = 60
Counter = 61
Counter = 62
Counter = 65
Counter = 68
Counter = 71
Counter = 74
Counter = 77
Counter = 80
Counter = 83
com.zwchen.servlet.SimpleServlet@11e1bbf ==> Thread[http-8081-Processor22,5,main]:
Counter = 61
Counter = 63
Counter = 66
Counter = 69
Counter = 72
Counter = 75
Counter = 78
Counter = 81
Counter = 84
Counter = 87
com.zwchen.servlet.SimpleServlet@11e1bbf ==> Thread[http-8081-Processor24,5,main]:
Counter = 61
Counter = 64
Counter = 67
Counter = 70
Counter = 73
Counter = 76
Counter = 79
Counter = 82
Counter = 85
Counter = 88
我们会发现三点:
servlet只产生了一个Servlet对象,因为输出this时,其hashcode都一样,
servlet在不同的线程(线程池)中运行,如http-8081-Processor22,http-8081-Processor23
Count被这三个doGet方法共享,并且并行修改。
上面的结果,违反了线程安全的两个方面。
那么,我们怎样保证按照我们期望的结果运行呢?首先,我想保证产生的count都是顺序执行的。
我们将Servlet代码重构如下:
我们的输出结果为:
com.zwchen.servlet.SimpleServlet@109da93:
Counter = 0
Counter = 1
Counter = 2
Counter = 3
Counter = 4
Counter = 5
Counter = 6
Counter = 7
Counter = 8
Counter = 9
com.zwchen.servlet.SimpleServlet@109da93:
Counter = 10
Counter = 11
Counter = 12
Counter = 13
Counter = 14
Counter = 15
Counter = 16
Counter = 17
Counter = 18
Counter = 19
com.zwchen.servlet.SimpleServlet@109da93:
Counter = 20
Counter = 21
Counter = 22
Counter = 23
Counter = 24
Counter = 25
Counter = 26
Counter = 27
Counter = 28
Counter = 29
这符合了我们的要求,输出都是按顺序的,这正式synchronized的含义。
附带说一下,我现在synchronized的是一个字符串变量mutex,不是this对象,这主要是从performance和Scalability考虑。Synchronized用在this对象上,会带来严重的可伸缩性的问题(Scalability),所有的并发请求都要排队!
1,synchronized(mutex)与synchronized(this)在这里是一样的,因为mutex是实例变量;
2,{}里面到代码每次只能有一个线程执行
你的问题太长,没耐心看了。我纯粹路过 :shock:
1,线程安全问题导致的现象是不确定的,有线程安全问题的代码不一定每次跑都会出现问题;
2,synchronized(obj){},是获取对象obj的对象锁,{}中的代码一次只可以一个线程访问,文中的mutex是Servlet的实例变量,所以当前servlet的所有http处理线程都会在这里同步;
3,synchronized(req)是没有意义的,因为每个http请求Servlet容器都会独立创建一个HttpServletRequest,它不被其他的http线程共享;
4,你的“最关键的:”里面的sleep代码和是否线程安全没关系,原文作者让每个http线程sleep一个随机的时间间隔是为了模拟Http请求处理的不确定的时延