public class Demo {
    private int num=10;
    //未加synchronized修饰的sell方法
    public synchronized void sell(){
        if(num==0){
            return;
        }
        num--;
        System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+num+"张");
    }
    class window implements Runnable{
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true){
                sell();
                try {
                    Thread.sleep(1000*2);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
    }
    public static void main(String[] args) {
        Demo d = new Demo();
        window w = d.new window();
        new Thread(w,"窗口1").start();
        new Thread(w,"窗口2").start();
        new Thread(w,"窗口3").start();
        new Thread(w,"窗口4").start();
        
    }
输出结果:
窗口1卖出一张票,剩余6张
窗口4卖出一张票,剩余7张
窗口3卖出一张票,剩余8张
窗口2卖出一张票,剩余5张
窗口4卖出一张票,剩余3张
窗口3卖出一张票,剩余3张
窗口1卖出一张票,剩余4张
窗口4卖出一张票,剩余1张
窗口1卖出一张票,剩余0张
窗口2卖出一张票,剩余1张
窗口3卖出一张票,剩余1张
很明显这不是我们想要的结果 导致这种结果的原因就是没有对sell方法加锁造成的
举个例子,int i=10; 开启两个进程 进程1和进程2 同时执行i=i-1操作并输出,
假设进程1先开始运行
进程1运行过程中,首先会先把i读取到内存当中,然后cpu从内存中读取i,执行i-1,最后将结果i=9刷新到内存中. 在整个过程中,某一时间段(cpu进行计算后,将结果返回内存前)存在两个i值,即内存中i=10 cpu中i=9;
这个时候若进程2读取i的值,读取的是内存中i的值 10,并不是进程1操作了i的结果值 9,因为此时进程1还未将计算结果刷新到内存;这便导致了明明执行了两次i-1操作结果却i=9;
为了避免这种情况,我们要对sell方法加锁(synchronized)
打个比方,一群人(多线程)去参观一座庄园(一个实体类的对象),里面有很多房子(方法),有的房子有锁(加了synchronized关键字),有的无锁(未加synchronized关键字),无锁的房子可随意由大家参观,而有锁的房子在门口放了把钥匙,当有人(进程)想进入房间(执行该方法),他首先会用钥匙打开房门然后带着钥匙进入房间,这样便不会有人进去打扰他参观,当他参观完后 走出房间将钥匙放在外面留给下一个想要参观的人(需要执行该方法的其他进程).
如此便避免了多个线程对共享资源操作发生冲突
让我们看一下synchronized修饰了方法之后的运行结果
    //加了synchronized修饰的sell方法
    public synchronized void sell(){
        if(num==0){
            return;
        }
        num--;
        System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+num+"张");
    }运行结果:
窗口1卖出一张票,剩余9张
窗口4卖出一张票,剩余8张
窗口3卖出一张票,剩余7张
窗口2卖出一张票,剩余6张
窗口3卖出一张票,剩余5张
窗口2卖出一张票,剩余4张
窗口4卖出一张票,剩余3张
窗口1卖出一张票,剩余2张
窗口4卖出一张票,剩余1张
窗口2卖出一张票,剩余0张
这才是我们想要的结果;
synchronized如果用来修饰方法,作用范围则是调用这个方法的对象 若按照下述方法开启进程 则依然是错误的结果
<pre name="code" class="java">public static void main(String[] args) {
		Demo d = new Demo();
		new Thread(d.new window(),"窗口1").start();
		new Thread(d.new window(),"窗口2").start();
		new Thread(d.new window(),"窗口3").start();
		new Thread(d.new window(),"窗口4").start();
		
	}原文:http://blog.csdn.net/qq_28701323/article/details/51331035