java多线程笔记–synchronized类,对象,方法,代码块

导读:本篇文章讲解 java多线程笔记–synchronized类,对象,方法,代码块,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

java多线程笔记–synchronized的用法

* 0)对象锁是用于对象实例方法,或者一个对象实例上的,
* 类锁是用于类的静态方法或者一个类的class对象上的(单例模式的双重检测)
* 一个线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁
* 1)synchronized类,和synchronized对象(this)
* //synchronized(this)代表锁住同一对象。多个线程竞争锁访问同一对象,对不同对象不竞争
* //synchronized(CountRunnable.class)代表锁住整个CountRunnable类的对象。多个线程对同一类的多个对象也竞争锁访问
* 2)synchronized方法和synchronized代码块
* 同步代码块比同步方法粒度小;一般需要加锁进行同步的时候,肯定是范围越小越好,这样性能更好
* synchronized方法和synchronized代码块(synchronized(this))都是锁当前对象
* 3)当一个线程访问object的一个synchronized(this)同步代码块时,
* 另一个线程仍然可以访问该object中的非synchronized(this)同步代码块
* 4)线程访问synchronized内的代码时,会隐式地获取锁,执行完括号中的代码,会隐式地释放锁

1.锁对象, 多线程售票示例

package com.ctg.test.thread;

/**
 * @Description: 1)synchronized 类
 * 2)synchronized对象(this)
 * 3)synchronized方法
 * 4)synchronized代码块
 * @Author: 
 * @Date: 2019/5/22 21:48
 */
public class TestSynchronizedTicket {
    private static int num = 10;

    public static void main(String[] args) {
        TicketRunnable ticketRunnable = new TicketRunnable(num);
        Thread t1 = new Thread(ticketRunnable, "窗口1");
        Thread t2 = new Thread(ticketRunnable, "窗口2");
        Thread t3 = new Thread(ticketRunnable, "窗口3");
        t1.start();
        t2.start();
        t3.start();

    }

    public static class TicketRunnable implements Runnable {
        private int ticket;

        public TicketRunnable(int ticket) {
            this.ticket = ticket;
        }

        @Override
        public void run() {
            while (ticket > 0) {
                //锁对象,多个线程竞争访问同一个对象TicketRunnable ticketRunnable = new TicketRunnable(num)
                synchronized (this) {
                    if (ticket > 0) {
                        try {
                            ticket--;
                            Thread.sleep(100);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在卖票,还剩:" + ticket);
                    }else{
                        System.out.println(Thread.currentThread().getName() + "票已卖完" );

                    }

                }

            }

        }
    }
}

在这里插入图片描述

2.synchronized类,对象,方法,代码块示例

package com.ctg.test.thread;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Description:

 * @Author:
 * @Date: 2019/5/22 23:34
 */
public class Service {
    //类锁,锁 静态方法,和f2 f3不竞争
    public static synchronized void f0(){
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        System.out.println(df.format(new Date())+";"+Thread.currentThread().getName()+":"+"f0");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //类锁,锁 类.class,和f2 f3不竞争
    public void f1(){
        synchronized (Service.class) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
            System.out.println(df.format(new Date())+";"+Thread.currentThread().getName()+":"+"f1");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //锁方法,f2 f3竞争(锁的也是当前对象)
    public synchronized void f2(){
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        System.out.println(df.format(new Date())+";"+Thread.currentThread().getName()+":"+"f2");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //锁代码块,f2 f3竞争,如果用了同步代码块,那么当退出代码块时就已经释放了对象锁(当前对象this进行加锁)
    public void f3(){
        //
        synchronized (this) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
            System.out.println(df.format(new Date())+";"+Thread.currentThread().getName()+":"+"f3");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //
    }
    //锁普通对象,跟f2 f3不竞争
    public void f4(){
        String str="test";
        synchronized (str) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
            System.out.println(df.format(new Date())+";"+Thread.currentThread().getName()+":"+"f4");
        }
    }

}

测试:

package com.ctg.test.thread;

/**
 * @Description:
 * 0)对象锁是用于对象实例方法,或者一个对象实例上的,
 * 类锁是用于类的静态方法或者一个类的class对象上的(单例模式的双重检测)
 * 一个线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁
 * 1)synchronized类,和synchronized对象(this)
 * //synchronized(this)代表锁住同一对象。多个线程竞争锁访问同一对象,对不同对象不竞争
 * //synchronized(CountRunnable.class)代表锁住整个CountRunnable类的对象。多个线程对同一类的多个对象也竞争锁访问
 * 2)synchronized方法和synchronized代码块
 * 同步代码块比同步方法粒度小;一般需要加锁进行同步的时候,肯定是范围越小越好,这样性能更好
 * synchronized方法和synchronized代码块(synchronized(this))都是锁当前对象
 * 3)当一个线程访问object的一个synchronized(this)同步代码块时,
 * 另一个线程仍然可以访问该object中的非synchronized(this)同步代码块
 * 4)线程访问synchronized内的代码时,会隐式地获取锁,执行完括号中的代码,会隐式地释放锁
 * @Author: 
 * @Date: 2019/5/22 21:48
 */
public class TestSynchronized {
    /**
     * 执行结果:f0 f1竞争访问,类锁,和f4不竞争锁
     * f2 f3竞争访问对象锁,和f4不竞争锁
     * @param args
     */
    public static void main(String[] args) {
        Service service=new Service();
        Thread t0 = new Thread(new Runnable() {
            @Override
            public void run() {
                Service.f0();
            }
        },"线程0");

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                service.f1();
            }
        },"线程1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                service.f2();
            }
        },"线程2");
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                service.f3();
            }
        },"线程3");
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                service.f4();
            }
        },"线程4");
        t0.start();
        t1.start();
//        t2.start();
//        t3.start();
//        t4.start();

    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/18357.html

(0)
小半的头像小半

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!