zoukankan      html  css  js  c++  java
  • java synchronized详解

    synchronized是Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
    不适用synchronized修饰代码的情况:

    public class SynchornizedTest implements Runnable{
    
        public static void main(String[] args) {
            SynchornizedTest st = new SynchornizedTest();
            Thread ta = new Thread(st, "A");
            Thread tb = new Thread(st, "B");
            ta.start();
            tb.start();
        }
        @Override
        public void run() {
            for (int i = 0; i < 5; i ++) {
                System.out.println(Thread.currentThread().getName() + " loop " + i);
            }
        }
    }

    运行结果:

    A loop 0
    B loop 0
    A loop 1
    B loop 1
    A loop 2
    B loop 2
    A loop 3
    A loop 4
    B loop 3
    B loop 4

    A B两线程交替执行

    使用synchronized修饰代码块:

    synchronized (this) {
        for (int i = 0; i < 5; i ++) {
            System.out.println(Thread.currentThread().getName() + " loop " + i);
        }
    }

    运行结果:

    A loop 0
    A loop 1
    A loop 2
    A loop 3
    A loop 4
    B loop 0
    B loop 1
    B loop 2
    B loop 3
    B loop 4

    两个线程独自占有CPU资源,一个线程结束后另一个线程才能执行。

    总结

    当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

    但是当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

    
    public class SynchornizedTest1 {
    
        public void funWithSyn(){
            synchronized (this) {
                for (int i = 0; i < 5; i ++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " : "+i);
                }
            }
        }
    
        public void fun(){
            for (int i = 0; i < 5; i ++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " : "+i);
            }
        }
    
        public static void main(String[] args) {
            final SynchornizedTest1 st = new SynchornizedTest1();
            Thread t1 = new Thread(new Runnable() {
                public void run() {
                    st.fun();
                }
            },"t1");
            Thread t2 = new Thread(new Runnable() {
                public void run() {
                    st.funWithSyn();
                }
            },"t2");
            t1.start();
            t2.start();
        }
    
    }

    运行结果:

    t1 : 0
    t2 : 0
    t2 : 1
    t1 : 1
    t2 : 2
    t1 : 2
    t2 : 3
    t1 : 3
    t1 : 4
    t2 : 4

    funWithSyn方法使用synchronized修饰,而fun方法没有,t2访问同步代码块时,t2仍可以访问非同步代码块。

    当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

    修改fun方法,加上synchronized,结果如下:

    t1 : 0
    t1 : 1
    t1 : 2
    t1 : 3
    t1 : 4
    t2 : 0
    t2 : 1
    t2 : 2
    t2 : 3
    t2 : 4

    也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

  • 相关阅读:
    044 文件和数据格式化
    040 字典类型及操作
    042 实例10-文本词频统计
    Java中PreparedStatement和Statement的用法区别(转)
    java连接oracle的简单实例
    javamail发送邮件的简单实例(转)
    JAVA IO之管道流总结大全(转)
    缓冲流和转换流(转)
    使用缓冲流来读写文件(转)
    JAVA向文件中追加内容(转)
  • 原文地址:https://www.cnblogs.com/lolau/p/7157901.html
Copyright © 2011-2022 走看看