java同步synchronized详解

       synchronized可以修饰代码块也可以修饰方法,还可以作用于静态方法,类和某个实例

       每个对象都有一把锁,当多个线程同时访问共享资源的时候,需要用到synchronized,synchronized分为代码块和方法,代码块需要显示的指定对象,而方法不需要(即当前对象)。

        java的内存模型是对每一个进程都有主内存,每个线程也有自己的内存,它们从主内存中取数据,然后在计算,在存入主内存。

         例子:现在有两个线程A,B线程,A线程对变量i加1,B线程同时对i加2,这两个线程同时操作,如果没有同步处理则B线程做的操作会覆盖A线程的操作。

         这时可以用synchronized处理,synchronized具有原子性,原子操作:取数据,操作数据,存数据。synchronized可以保证同一时间只有一个线程操作该对象。

        java中对非Long和Float原始数据类型的存,取为原子操作。其实就是对一个字节的存,取操作,由于Float和Long为两个字节,所以其取,存为非原子操作。如果想把他们变成原子操作可以用volatile.

        作用区域主要有两种:

        (1)、方法

        (2)、代码块

          对于用一对像的同步操作只能有一个线程,而对于不同对象是互不干扰的。

  Public synchronized void change() {
     //同步方法
  }
  Public void change() { 
      Synchronized(this) {
          //同步语句:(因为效率问题,有时考虑使用同步语句块)
      }
   }

   同步方法是针对当前对象的,如果不针对当前对象,而是针对其他对象可以用同步语句,如:

private byte[]  lock= new byte[0];
 
  Public void change() {
    Synchronized(lock) {
  }
}

自定义锁注意:

   a、对象必须为private防止其他类对象访问

   b、geter方法最好clone一个对象返回

其他用法

      可以针对静态方法和类

Class Foo   {   
public synchronizedstatic void methodAAA()// 同步的static 函数  
{   
//….  
}  
  public void methodBBB()   {   
       synchronized(Foo.class)
             // class literal(类名称字面常量) 
 } 
}

  它是针对整个类的,所以只能是同一个类的一个线程进行访问

  synchronized(this)与synchronized(static class)的区别:

     synchronized就是针对内存区块申请内存锁,this是类的一个对象,也就是针对相同对象的互斥操作,其他线程可以访问该类的其他对象。static是针对类,static是整个类共有的,也就是该类的所有成员间互斥。在同一时间只有一个线程可以访问该类的实例。

建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。代码如下:

public class MyThreadPrinter2 implements Runnable {     
    
    private String name;     
    private Object prev;     
    private Object self;     
    
    private MyThreadPrinter2(String name, Object prev, Object self) {     
        this.name = name;     
        this.prev = prev;     
        this.self = self;     
    }     
    
    @Override    
    public void run() {     
        int count = 10;     
        while (count > 0) {     
            synchronized (prev) {     
                synchronized (self) {     
                    System.out.print(name);     
                    count--;    
                      
                    self.notify();     
                }     
                try {     
                    prev.wait();     
                } catch (InterruptedException e) {     
                    e.printStackTrace();     
                }     
            }     
    
        }     
    }     
    
    public static void main(String[] args) throws Exception {     
        Object a = new Object();     
        Object b = new Object();     
        Object c = new Object();     
        MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);     
        MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);     
        MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);     
             
             
        new Thread(pa).start();  
        new Thread(pb).start();  
        new Thread(pc).start();    }     
}


转载于:https://my.oschina.net/u/2419606/blog/541065

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值