多线程--线程同步

来源:互联网 发布:centos wget 命令 编辑:程序博客网 时间:2024/05/22 02:04

一、概念

线程同步机制线程同步机制是为了解决多线程之间由于对共享数据在同一时刻的操作而可能产生的安全问题而提出的,比如下面的例子

public class Foo {    private int x = 100;    public int getX() {        return x;    }    public int fix(int y) {        x = x - y;        return x;    }}
public class MyRunnable implements Runnable {    private Foo foo = new Foo();    public static void main(String[] args) {        MyRunnable run = new MyRunnable();        Thread ta = new Thread(run, "Thread-A");        Thread tb = new Thread(run, "Thread-B");        ta.start();        tb.start();    }    public void run() {        for(int i = 0; i < 3; i++) {            this.fix(30);            try{                Thread.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + " : 当前foo对象的x值= " + foo.getX());        }    }   public int fix(int y) {        return foo.fix(y);    }}

运行结果:
<pre>Thread-B : 当前foo对象的x值= 40Thread-A : 当前foo对象的x值= 40Thread-B : 当前foo对象的x值= -20Thread-A : 当前foo对象的x值= -20Thread-B : 当前foo对象的x值= -80Thread-A : 当前foo对象的x值= -80

二、在具体的Java代码中需要完成以下两个操作:

  1. 把竞争访问的资源类Foo变量x标识为private;
  2. 同步那些修改变量的代码,使用synchronized关键字同步方法或代码

三、那么什么东西能作为锁呢?

  1. 对象级别锁(对于访问非静态共享资源):作为锁的条件:任意类实例对象(包括本类实例对象this)
  2. 类级别锁(对于访问静态共享资源):作为锁的条件:类名.class

四、利弊分析
  1. 好处:解决了线程安全问题。
  2. 坏处:需要多个线程去判断锁,较为消耗资源。(好比家里不加锁,则直接开门能进;加上锁之后还要开锁)

五、注意

  1. 一个对象作为同步块的锁时,其他线程对于该对象的非同步方法的调用不会受影响。
  2. 非静态同步函数的锁是该对象的内置锁,即this。
  3. 因为静态函数中不能使用this,如果同步函数被静态修饰后,使用的锁不是this。而是该类的class对象,即对象名.class
  4. 当程序运行到synchronized同步方法或代码块时该对象锁才起作用。
  5. 一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。
  6. 释放锁是指持锁线程退出了synchronized同步方法或代码块。
  7. 线程睡眠时,它所持的任何锁都不会释放
  8. 线程可以获得多个锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁。
  9. 同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块。










0 0