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

Posted SingleOneMan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java多线程笔记--synchronized类,对象,方法,代码块相关的知识,希望对你有一定的参考价值。

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();

    



以上是关于java多线程笔记--synchronized类,对象,方法,代码块的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记之多线程笔记

Java多线程学习笔记— “隐式同步锁(synchronized)与显式同步锁(lock)”

JAVA笔记(19)--- 线程概述;如何实现多线程并发;线程生命周期;Thread常用方法;终止线程的三种方式;线程安全问题;synchronized 实现同步线程模型;

Java多线程学习篇synchronized

Java学习笔记—多线程(java.util.concurrent.locks包,转载)

3.java多线程学习笔记之共享模型之管程