package unit_fifteen;

public class Foo {
    private int x = 100;

    public int getX() {
        return x;
    } 

    public int fix(int y) {
        x = x - y; 
        return x;
    } 
}


package unit_fifteen;

public class MyRunnable implements Runnable {
    private Foo foo =new Foo(); 

    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread ta = new Thread(r,"Thread-A"); 
        Thread tb = new Thread(r,"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);
    } 
}


Thread-B :当前foo对象的x值= 40
Thread-A :当前foo对象的x值= 10
Thread-A :当前foo对象的x值= -20
Thread-B :当前foo对象的x值= -50
Thread-B :当前foo对象的x值= -80
Thread-A :当前foo对象的x值= -80

从结果发现,这样的输出值明显是不合理的,且结果是变动的,原因是两个线程不加控制的访问Foo对象并修改其数据所致;如果要保持结果的合理性,只需要达到一个目的,就是将对Foo的访问加以限制,每次只能有一个线程在访问

    Java中一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁;释放锁是指持锁线程退出了synchronized同步方法或代码块;线程睡眠时,它所持的任何锁都不会释放;线程可以获得多个锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁;同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块

当然,同步方法也可以改写为非同步方法,但功能完全一样的,例如:

    public synchronized int getX() {
        return x++;
    }

package unit_fifteen;

public class Test {
    public static void main(String[] args) {
            User u = new User("张三", 100);
            MyThread t1 = new MyThread("线程A", u, 20);
            MyThread t2 = new MyThread("线程B", u, -60);
            MyThread t3 = new MyThread("线程C", u, -80);
            MyThread t4 = new MyThread("线程D", u, -30);
            MyThread t5 = new MyThread("线程E", u, 32);
            MyThread t6 = new MyThread("线程F", u, 21);

            t1.start(); 
            t2.start(); 
            t3.start(); 
            t4.start(); 
            t5.start(); 
            t6.start(); 
    } 
} 

class MyThread extends Thread { 
    private User u;
    private int y = 0;

    MyThread(String name, User u, int y) {
            super(name);
            this.u = u;
            this.y = y;
    } 

    public void run() {
            u.oper(y); 
    } 
} 

class User { 
    private String code;
    private int cash;

    User(String code, int cash) {
            this.code = code;
            this.cash = cash;
    } 

    public String getCode() {
            return code;
    } 

    public void setCode(String code) {
            this.code = code;
    } 

    /** 
     * 业务方法
     * @param x 添加x万元
     */ 
    public synchronized void oper(int x) {
            try {
                    Thread.sleep(10L); 
                    this.cash += x;
                    System.out.println(Thread.currentThread().getName() + "运行结束,增加“" + x +"”,当前用户账户余额为:" + cash);
                    Thread.sleep(10L); 
            } catch (InterruptedException e) {
                    e.printStackTrace(); 
            } 
    } 

    @Override 
    public String toString() {
            return"User{" +
                            "code='" + code + '\'' +
                            ", cash=" + cash +
                            '}'; 
    } 
}

    public int getX() {
        synchronized (this) {
            return x;
        }
    }

package unit_fifteen;

public class Test {
    public static void main(String[] args) {
            User u = new User("张三", 100);
            MyThread t1 = new MyThread("线程A", u, 20);
            MyThread t2 = new MyThread("线程B", u, -60);
            MyThread t3 = new MyThread("线程C", u, -80);
            MyThread t4 = new MyThread("线程D", u, -30);
            MyThread t5 = new MyThread("线程E", u, 32);
            MyThread t6 = new MyThread("线程F", u, 21);

            t1.start(); 
            t2.start(); 
            t3.start(); 
            t4.start(); 
            t5.start(); 
            t6.start(); 
    } 
} 

class MyThread extends Thread { 
    private User u;
    private int y = 0;

    MyThread(String name, User u, int y) {
            super(name);
            this.u = u;
            this.y = y;
    } 

    public void run() {
            u.oper(y); 
    } 
} 

class User { 
    private String code;
    private int cash;

    User(String code, int cash) {
            this.code = code;
            this.cash = cash;
    } 

    public String getCode() {
            return code;
    } 

    public void setCode(String code) {
            this.code = code;
    } 

    /** 
     * 业务方法
     * 
     * @param x 添加x万元
     */ 
    public void oper(int x) {
            try {
                    Thread.sleep(10L); 
                    synchronized (this) {
                            this.cash += x;
                            System.out.println(Thread.currentThread().getName() +"运行结束,增加“" + x +"”,当前用户账户余额为:" + cash);
                    } 
                    Thread.sleep(10L); 
            } catch (InterruptedException e) {
                    e.printStackTrace(); 
            } 
    } 

    @Override 
    public String toString() {
            return"User{" +
                            "code='" + code + '\'' +
                            ", cash=" + cash +
                            '}'; 
    } 
}

 

效果是完全一样的

    要同步静态方法,需要一个用于整个类对象的锁,这个对象是就是这个类(XXX.class)

例如:

public static synchronized int setName(String name){

      Xxx.name = name;

}

等价于
public static int setName(String name){
      synchronized(Xxx.class){
            Xxx.name = name;
      }
}

     注意:对于同步,要时刻清醒在哪个对象上同步,这是关键

     死锁对Java程序来说,是很复杂的,也很难发现问题。当两个线程被阻塞,每个线程在等待另一个线程时就发生死锁

package unit_fifteen;

public class Test {
    public static void main(String[] args) {
        DeadlockRisk dead = new DeadlockRisk();
        MyThread t1 = new MyThread(dead, 1, 2);
        MyThread t2 = new MyThread(dead, 3, 4);
        MyThread t3 = new MyThread(dead, 5, 6);
        MyThread t4 = new MyThread(dead, 7, 8);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }

}

class MyThread extends Thread {
    private DeadlockRisk dead;
    private int a, b;

    MyThread(DeadlockRisk dead, int a, int b) {
        this.dead = dead;
        this.a = a;
        this.b = b;
    }

    @Override
    public void run() {
        dead.read();
        dead.write(a, b);
    }
}

class DeadlockRisk {
    private static class Resource {
        public int value;
    }

    private Resource resourceA = new Resource();
    private Resource resourceB = new Resource();

    public int read() {
        synchronized (resourceA) {
            System.out.println("read():" + Thread.currentThread().getName()
                    + "获取了resourceA的锁!");
            synchronized (resourceB) {
                System.out.println("read():" + Thread.currentThread().getName()
                        + "获取了resourceB的锁!");
                return resourceB.value + resourceA.value;
            }
        }
    }

    public void write(int a, int b) {
        synchronized (resourceB) {
            System.out.println("write():" + Thread.currentThread().getName()
                    + "获取了resourceA的锁!");
            synchronized (resourceA) {
                System.out.println("write():"
                        + Thread.currentThread().getName() + "获取了resourceB的锁!");
                resourceA.value = a;
                resourceB.value = b;
            }
        }
    }
}