您的位置:首页 > 编程语言 > Java开发

关于java关键字synchronized的一些心得体会

2014-08-01 16:03 351 查看
关于java关键字synchronized的一些心得体会

         最近遇到了与synchronized有关的问题, 所以就对她研究了一下下,来解决现在遇到的问题和一直以来对它的陌生感。
         还是先从问题入手吧,最近遇到了一个用户在同一时间重复领奖的问题。经过分析,这是一个很严重的系统BUG(庆幸没有hackers对这个下手,都是钱啊

 ),很有可能是这个用户同时发送了2个领奖的请求,突破了我们为他们设置的两个障碍;当然经过我的研究发现第一个障碍就是个摆设,第二个障碍是每到一个重要的节点我们便访问数据库并取出领奖状态,但是第二个障碍也是有问题的,但在这里就不细说了,重点说说第一个吧。
        我们在领奖的action中对当前action对象加了同步锁synchronized,就像这样:
/**
* 领取

* @return
*/
@Action(映射路径)
public String receive() {
synchronized (this) { // 此操作必须同步
step(0x0501);
}
return "RECEIVE";

这是struts2的一个Action,从上面的代码我们可以看到锁住的是this也就是当前的Action对象,被锁住的代码块是step()方法。这就是我们设立的第一个障碍,希望能够在同一个时刻只有1个请求(线程)被执行。为了验证效果,我搭建了一个struts2的环境来模拟并发,看是否能够锁住。

public class TestAction extends ActionSupport {
    /** 
    * 
    */
    private static final long serialVersionUID = -6758668004128012679L;
    //private static Model m=new Model();//静态对象Model

    private Model m=new Model();//对象Model  
    private String rr;//请求要传递过来的参数,用来区分2个不同的请求

    public void setRr(String rr) {
        this.rr = rr;
    }
    @Action(映射路径) 

    public String getTest(){
        System.out.println("Model对象:"+m);
        synchronized(this) {//这个是对TestAction加同步锁
        //synchronized(m) { 这个是对Model对象加同步锁

            m.printSomething(rr);
        } 
        return "TEST"; 
    }
}

public class Model {
       public void printSomething(String rr) {

            int i = 0;
            while (i < 5) {
                System.out.println("该对象中的i每隔一段时间就会递增:" + i);
                System.out.println("所属请求:“+rr);
                long j = 0;
                long startTime = new Date().getTime();
                while (j < 1000) {//每隔一秒循环1次
                    long endTime = new Date().getTime();
                    j = endTime - startTime;
                }
                i++;
            }
      }
}

第一次实验:Model对象用是动态创建的,锁的是:synchronized(m),然后发送2个请求后控制台打印的结果:

Model对象:pkg.Model@4f5ed675
该对象中的i每隔一段时间就会递增:0
所属请求:2
Model对象:pkg.Model@3ebce805
该对象中的i每隔一段时间就会递增:0
所属请求:1
该对象中的i每隔一段时间就会递增:1
所属请求:2
该对象中的i每隔一段时间就会递增:1
所属请求:1
该对象中的i每隔一段时间就会递增:2
所属请求:2
该对象中的i每隔一段时间就会递增:2
所属请求:1
该对象中的i每隔一段时间就会递增:3
所属请求:2
该对象中的i每隔一段时间就会递增:3
所属请求:1
该对象中的i每隔一段时间就会递增:4
所属请求:2
该对象中的i每隔一段时间就会递增:4
所属请求:1

 从打印出来的结果可以看出有2个不同的Model对象,2个不同的请求,它们都在执行,所以出现了交替打印的情况。

 第二次实验:Model对象用是静态创建的,锁的是:synchronized(m),然后发送2个请求后控制台打印的结果:

Model对象:pkg.Model@8227089
该对象中的i每隔一段时间就会递增:0
所属请求:1
Model对象:pkg.Model@8227089
该对象中的i每隔一段时间就会递增:1
所属请求:1
该对象中的i每隔一段时间就会递增:2
所属请求:1
该对象中的i每隔一段时间就会递增:3
所属请求:1
该对象中的i每隔一段时间就会递增:4
所属请求:1
该对象中的i每隔一段时间就会递增:0
所属请求:2
该对象中的i每隔一段时间就会递增:1
所属请求:2
该对象中的i每隔一段时间就会递增:2
所属请求:2
该对象中的i每隔一段时间就会递增:3
所属请求:2
该对象中的i每隔一段时间就会递增:4
所属请求:2 

从打印出来的结果可以看出只有1个Model对象,2个不同的请求,请求1先执行完,在执行的请求2.说明这个同步锁是成功的。

这两个实验得出的结论是:synchronized同步锁锁定对象时,必须是同一个对象才能锁定,否则没有效果。 

那么synchronized(this)有没有作用呢,做第三个实验,把synchronized(m)换成synchronized(this)

Model对象:pkg.Model@327d8933
该对象中的i每隔一段时间就会递增:0
所属请求:1
Model对象:pkg.Model@327d8933
该对象中的i每隔一段时间就会递增:0
所属请求:2
该对象中的i每隔一段时间就会递增:1
所属请求:1
该对象中的i每隔一段时间就会递增:1
所属请求:2
该对象中的i每隔一段时间就会递增:2
所属请求:1
该对象中的i每隔一段时间就会递增:2
所属请求:2
该对象中的i每隔一段时间就会递增:3
所属请求:1
该对象中的i每隔一段时间就会递增:3
所属请求:2
该对象中的i每隔一段时间就会递增:4
所属请求:1
该对象中的i每隔一段时间就会递增:4
所属请求:2

  从打印出来的结果可以看出只有1个Model对象,2个不同的请求,它们都在执行,所以出现了交替打印的情况。

这个实验说明synchronized没有锁定Model对象, 这是因为private static Model m=new Model();这种方式创建的Model不属于TestAction类,值得注意的是struts2相较于struts1而言,struts2是一个请求对应1个action,struts1是一个action在处理多个请求,因此在struts2中synchronized(this)起不到任何作用 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java