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