欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java基础Synchronized关键字之对象锁

程序员文章站 2022-05-29 12:23:50
java中Synchronized关键字之对象锁 当有多个线程对一个共享数据进行操作时,需要注意多线程的安全问题。 多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。而用的最多的就是synchronized关键字。 语法:Syn ......

java中synchronized关键字之对象锁

    当有多个线程对一个共享数据进行操作时,需要注意多线程的安全问题。

  多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。而用的最多的就是synchronized关键字。

  语法:synchronized(对象锁){}

  被synchronized关键字修饰的一个方法,则这个方法叫做同步方法

  当synchronized方法执行完或发生异常时,会自动释放锁。


 1.是否使用synchronized关键字的不同


 

package threaddemo;

public class threaddemo
{
    public static void main(string[] args)
    {
        example example = new example();

        thread t1 = new th(example);
        thread t2 = new th(example);

        t1.start();
        t2.start();
    }

}

class example
{
    public synchronized void show()
    {
        for (int i = 0; i < 10; ++i)
        {
            try
            {
                thread.sleep(500);
            }
            catch (interruptedexception e)
            {
                e.printstacktrace();
            }
            system.out.println(i);
        }
    }

}



class th extends thread
{
    private example example;

    public th(example example)
    {
        this.example = example;
    }

    @override
    public void run()
    {
        example.show();
    }

}

运行结果:

show()0
show()1
show()2
show()3
show()4
show()5
show()6
show()7
show()8
show()9
show2()0
show2()1
show2()2
show2()3
show2()4
show2()5
show2()6
show2()7
show2()8
show2()9

 

是否在show()方法前加上synchronized关键字,这个例子程序的执行结果会有很大的不同。

  如果不加synchronized关键字,则两个线程同时执行show()方法,输出是两组并发的。

  如果加上synchronized关键字,则会先输出一组0到9,然后再输出下一组,说明两个线程是顺次执行的。


 2.同步方法的锁是this


 

在静态同步方法中的对象锁是这个类的字节码文件对象。类.class

要想获取一个类的字节码文件对象,有两种方法

1通过当前类.class

2通过当前类的实例对象.getclass()方法获取

 

public class classdemo {
    void show(){
        //任何一个类可以通过.class来获取字节码文件对象
        class<classdemo> c = classdemo.class;
        //任何一个对象可以通过getclass()方法来获取字节码文件对象
        class<? extends classdemo> class1 = new classdemo().getclass();
        
    }
}

 

验证同步方法的对象锁是this

  思路:

  启动两个线程,让一个线程进入同步代码块,一个线程进入同步方法

  用到了一个中间的控制变量boolean flag

  线程对象的run中,实现三个窗口出售100张票的功能,让程序进入一个同步代码块中,并且在线程对象中,再定义一个同步方法,功能与同步代码块中的功能相同。

 

package threaddemo;

public class threaddemo03 {


public static void main(string[] args) {
t t = new t();
thread t1 = new thread(t);
thread t2 = new thread(t);

t1.start();
try {
thread.sleep(50);
} catch (exception e) {
e.printstacktrace();
}
t.flag=false;
t2.start();
}

}

class t implements runnable {
private int ticket = 100;
boolean flag = true;
object obj = new object();

@override
public void run() {
if (flag) {
while (true) {
//synchronized (this) {
synchronized (obj){
if (ticket > 0) {
try {
thread.sleep(50);
} catch (exception e) {
e.printstacktrace();
}
system.out.println(thread.currentthread().getname() + "正在出售第" + ticket-- + "张票");
}
}

}
}else{
while(true){
show();
}
}

}

public synchronized void show(){//synchronized (this)
if (ticket > 0) {
try {
thread.sleep(50);
} catch (exception e) {
e.printstacktrace();
}
system.out.println(thread.currentthread().getname() + "正在出售第" + ticket-- + "张票");
}
}

}

运行结果:

thread-0正在出售第100张票
thread-1正在出售第99张票
thread-0正在出售第98张票
thread-1正在出售第97张票
thread-0正在出售第96张票
thread-1正在出售第95张票
thread-0正在出售第94张票
thread-1正在出售第93张票
thread-0正在出售第92张票
thread-1正在出售第91张票
thread-0正在出售第90张票
thread-1正在出售第89张票
thread-0正在出售第88张票
thread-1正在出售第87张票
thread-0正在出售第86张票
thread-1正在出售第85张票
thread-0正在出售第84张票
thread-1正在出售第83张票
thread-0正在出售第82张票
thread-1正在出售第81张票
thread-0正在出售第80张票
thread-1正在出售第79张票
thread-0正在出售第78张票
thread-1正在出售第77张票
thread-0正在出售第76张票
thread-1正在出售第75张票
thread-0正在出售第74张票
thread-1正在出售第73张票
thread-0正在出售第72张票
thread-1正在出售第71张票
thread-0正在出售第71张票
thread-1正在出售第70张票
thread-0正在出售第69张票
thread-1正在出售第68张票
thread-0正在出售第68张票
thread-1正在出售第66张票
thread-0正在出售第67张票
thread-1正在出售第65张票
thread-0正在出售第65张票
thread-0正在出售第64张票
thread-1正在出售第63张票
thread-0正在出售第62张票
thread-1正在出售第61张票
thread-1正在出售第60张票
thread-0正在出售第59张票
thread-0正在出售第58张票
thread-1正在出售第57张票
thread-1正在出售第56张票
thread-0正在出售第55张票
thread-1正在出售第54张票
thread-0正在出售第54张票
thread-1正在出售第53张票
thread-0正在出售第52张票
thread-1正在出售第51张票
thread-0正在出售第50张票
thread-0正在出售第49张票
thread-1正在出售第48张票
thread-0正在出售第47张票
thread-1正在出售第47张票
thread-1正在出售第46张票
thread-0正在出售第45张票
thread-1正在出售第44张票
thread-0正在出售第43张票
thread-0正在出售第42张票
thread-1正在出售第41张票
thread-0正在出售第40张票
thread-1正在出售第39张票
thread-0正在出售第38张票
thread-1正在出售第37张票
thread-0正在出售第36张票
thread-1正在出售第35张票
thread-0正在出售第34张票
thread-1正在出售第33张票
thread-0正在出售第32张票
thread-1正在出售第31张票
thread-0正在出售第30张票
thread-1正在出售第29张票
thread-0正在出售第28张票
thread-1正在出售第27张票
thread-0正在出售第26张票
thread-1正在出售第25张票
thread-0正在出售第24张票
thread-1正在出售第23张票
thread-0正在出售第22张票
thread-1正在出售第21张票
thread-0正在出售第20张票
thread-1正在出售第19张票
thread-0正在出售第18张票
thread-1正在出售第17张票
thread-0正在出售第16张票
thread-1正在出售第15张票
thread-0正在出售第14张票
thread-1正在出售第13张票
thread-0正在出售第12张票
thread-1正在出售第11张票
thread-0正在出售第10张票
thread-1正在出售第9张票
thread-0正在出售第8张票
thread-1正在出售第7张票
thread-0正在出售第6张票
thread-1正在出售第5张票
thread-0正在出售第4张票
thread-1正在出售第3张票
thread-0正在出售第2张票
thread-1正在出售第1张票
thread-0正在出售第0张票

 

通过改变class t中同步代码块synchronized (对象锁) 的对象锁obj改成this依然成立。所以同步方法的对象锁是this。

其中public synchronized void show()就相当于synchronized (this)

静态同步方法的对象锁是类的字节码文件对象 类.class | 对象.getclass()

 

package threaddemo;

public class threaddemo2 {
    /*
     * 通过验证发现同步函数,如果被静态修饰后,不再以this为锁静态进内存时,内存中没有本类的对象,
     * 但一定有该类的字节码文件对象     类名.class
     * 该对象的类型是class 静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class
     */
    public static void main(string[] args) {
        ticket t = new ticket();
        thread t1 = new thread(t);
        thread t2 = new thread(t);
        // 开启第一个线程 但不一定马上执行
        t1.start();
        t.flag = false;// 改变标志
        try {
            thread.sleep(50);
        } catch (exception e) {
        } // 让主线程睡眠50毫秒 保证第一个线程先开始运行 且标志位改变
        t2.start();
    }
}
class ticket implements runnable {
    private static int ticket = 100;
    boolean flag = true;
    public void run() {
        if (flag) {
            while (true) {
                // synchronized(this)
                synchronized (ticket.class) {
                    if (ticket > 0) {
                        try {
                            thread.sleep(50);
                        } catch (exception e) {
                        }
                        system.out.println(thread.currentthread().getname() + "正在出售第" + ticket-- + "张票");
                    }
                }
            }
        } else
            while (true)
                show();
    }
    // 静态同步函数 该类对应的字节码文件对象为锁
    public static synchronized void show(){//synchronized (this)
        if (ticket > 0) {
            try {
                thread.sleep(50);
            } catch (exception e) {
            }
            system.out.println(thread.currentthread().getname() + "正在出售第" + ticket-- + "张票");
        }
    }
}

运行结果:

thread-0正在出售第100张票
thread-0正在出售第99张票
thread-0正在出售第98张票
thread-0正在出售第97张票
thread-0正在出售第96张票
thread-0正在出售第95张票
thread-0正在出售第94张票
thread-0正在出售第93张票
thread-0正在出售第92张票
thread-0正在出售第91张票
thread-1正在出售第90张票
thread-1正在出售第89张票
thread-1正在出售第88张票
thread-0正在出售第87张票
thread-1正在出售第86张票
thread-1正在出售第85张票
thread-0正在出售第84张票
thread-0正在出售第83张票
thread-1正在出售第82张票
thread-1正在出售第81张票
thread-0正在出售第80张票
thread-0正在出售第79张票
thread-1正在出售第78张票
thread-0正在出售第77张票
thread-1正在出售第76张票
thread-1正在出售第75张票
thread-1正在出售第74张票
thread-0正在出售第73张票
thread-0正在出售第72张票
thread-1正在出售第71张票
thread-1正在出售第70张票
thread-1正在出售第69张票
thread-0正在出售第68张票
thread-1正在出售第67张票
thread-0正在出售第66张票
thread-0正在出售第65张票
thread-0正在出售第64张票
thread-0正在出售第63张票
thread-0正在出售第62张票
thread-1正在出售第61张票
thread-1正在出售第60张票
thread-1正在出售第59张票
thread-0正在出售第58张票
thread-0正在出售第57张票
thread-0正在出售第56张票
thread-0正在出售第55张票
thread-0正在出售第54张票
thread-0正在出售第53张票
thread-0正在出售第52张票
thread-0正在出售第51张票
thread-1正在出售第50张票
thread-1正在出售第49张票
thread-0正在出售第48张票
thread-0正在出售第47张票
thread-0正在出售第46张票
thread-0正在出售第45张票
thread-0正在出售第44张票
thread-1正在出售第43张票
thread-1正在出售第42张票
thread-0正在出售第41张票
thread-1正在出售第40张票
thread-0正在出售第39张票
thread-0正在出售第38张票
thread-0正在出售第37张票
thread-0正在出售第36张票
thread-0正在出售第35张票
thread-0正在出售第34张票
thread-0正在出售第33张票
thread-0正在出售第32张票
thread-1正在出售第31张票
thread-1正在出售第30张票
thread-1正在出售第29张票
thread-1正在出售第28张票
thread-1正在出售第27张票
thread-1正在出售第26张票
thread-1正在出售第25张票
thread-1正在出售第24张票
thread-0正在出售第23张票
thread-0正在出售第22张票
thread-0正在出售第21张票
thread-1正在出售第20张票
thread-0正在出售第19张票
thread-0正在出售第18张票
thread-0正在出售第17张票
thread-1正在出售第16张票
thread-1正在出售第15张票
thread-1正在出售第14张票
thread-1正在出售第13张票
thread-0正在出售第12张票
thread-1正在出售第11张票
thread-0正在出售第10张票
thread-0正在出售第9张票
thread-0正在出售第8张票
thread-1正在出售第7张票
thread-0正在出售第6张票
thread-0正在出售第5张票
thread-0正在出售第4张票
thread-1正在出售第3张票
thread-1正在出售第2张票
thread-0正在出售第1张票