java中同步synchronized的意义,如何用它解决线程不安全的问题

马克-to-win:从上节我们学到,当多个线程访问且更改同一个变量时,很容易出现线程安全问题,诚然,我们可以通过一些其他手段,比如局部变量,多个实例,调整程序结构来解决线程安全问题,但是通常来讲,通过同步机制 synchronized来解决线程安全问题更加确定。比如,由于需求等其他限制条件决定,我们不能够用局部变量或多个实例或什么其他办法解决怎么办? synchronized为我们提供了比较确定的方法。换句话说,线程安全问题, synchronized基本能解决。分析上一节的线程安全问题,我们发现问题的起因主要是两个线程同时访问更改共同的变量造成的,只要我们让能够更改共同变量的方法序列的执行,(换句话就是一个执行完后,另一个再执行,) 就没问题了。如何实现呢? 用synchronized,现在针对上一节有问题的例子:1.8.1_b,我们只加一个字synchronized, 问题就解决了,马克- to-win:马克 java社区:防盗版实名手机尾号: 73203。



例1.9.1-本章源码

class Photoshop {
    private Photoshop() {
    }
    private static Photoshop photoshop = null;
    public synchronized static Photoshop getInstanceQixy() {
        if (photoshop == null) {
            photoshop = new Photoshop();
        }
        return photoshop;
    }
}
class MyThreadMark_to_win extends Thread {
    public void run() {
        Photoshop photoshopI1 = Photoshop.getInstanceQixy();
        System.out.println(Thread.currentThread().getName() + "实例是 "
                + photoshopI1);
    }
}
public class Test {
    public static void main(String[] args) {
        MyThreadMark_to_win mt1 = new MyThreadMark_to_win();
        MyThreadMark_to_win mt2 = new MyThreadMark_to_win();
        mt1.start();
        mt2.start();
    }
}

输出结果:

Thread-1实例是 Photoshop@a62fc3
Thread-0实例是 Photoshop@a62fc3

现在针对上一节有问题的例子:1.8.2_b,我们只加一个字synchronized, 问题也能解决,我们看一下。




例1.9.2-本章源码

class BookMark_to_win {
    int bookNum=10;
    synchronized void onlySellOne() {
        if (bookNum > 0) {
            System.out.println(Thread.currentThread().getName()
                    + " before" + bookNum);
            bookNum--;
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }
            System.out.println(Thread.currentThread().getName()
                    + " after " + bookNum);
        }
    }
}
class MyThread extends Thread {
    BookMark_to_win book;
    MyThread(BookMark_to_win tmp) {
        this.book = tmp;
    }
    public void run() {
/*run()里不能就只是写book.onlySellOne(), 因为会呈现
两个线程在那交替的效果*/      
        while (book.bookNum>0) {
            book.onlySellOne();
        }
    }
}
public class Test {
    public static void main(String[] args) {
        BookMark_to_win bookM = new BookMark_to_win();
        Thread t1 = new MyThread(bookM);
        Thread t2 = new MyThread(bookM);
        t1.start();
        t2.start();
    }
}

输出结果:

Thread-0 before10
Thread-0 after 9
Thread-0 before9
Thread-0 after 8
Thread-0 before8
Thread-0 after 7
Thread-0 before7
Thread-0 after 6
Thread-1 before6
Thread-1 after 5
Thread-1 before5
Thread-1 after 4
Thread-0 before4
Thread-0 after 3
Thread-0 before3
Thread-0 after 2
Thread-0 before2
Thread-0 after 1
Thread-0 before1
Thread-0 after 0

if (bookNum > 0) {直接执行完了,就可以退出synchronized块儿了,要想不切换,就if变成while,就一个线程知道执行完为止。),完美配合,从10到0,一个一个的递减。perfect!