synchroized关键字总结:
类锁:
synchronized(类.class){…}
synchronized修饰静态方法
对象锁:
synchronized(this){…}
synchronized(自定义内部对象实例){…}
synchronized修饰普通方法
使用对象锁的情况:所有的线程共用一个对象实例才会保证线程安全.我的理解是同一对象实例才能保证锁是唯一.
使用类锁的情况:是所有线程共享的锁(就是所有线程共享一把类锁),所以同一时刻,只能有一个线程使用加了锁的方法或方法体,不管是不是同一个实例都只允许一个线程访问.
以上是从对象类的维度进行分类,也可以从使用方式上分类:
普通方法:对象锁
静态方法:类锁
代码块:对象锁(this/自定义内部对象)类锁(类名.class)
卖票问题解决方案:
1.使用synchroized锁对象:
1.1使用this关键字:
售票类:
public class SaleTicket {
private static int ticketCount=100;
public void saleTicket(){
while (ticketCount>0){
// 锁对象:synchronized (this){}
synchronized (this){
if (ticketCount > 0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticketCount+"张票");
--ticketCount;
}else {
System.out.println("票卖完了");
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
线程类:
public class TicketThread extends Thread{
private SaleTicket saleTicket;
public TicketThread(SaleTicket saleTicket) {
this.saleTicket=saleTicket;
}
@Override
public void run() {
saleTicket.saleTicket();
}
}
测试类:
public static void main(String[] args) {
SaleTicket saleTicket = new SaleTicket();
new TicketThread(saleTicket).start();
new TicketThread(saleTicket).start();
}
1.2使用自定义内部对象实例:
售票类:
public class SaleTicket {
private static int ticketCount=100;
private Object obj=new Object();
public void saleTicket(){
while (ticketCount>0){
// 锁对象,自定义对象
synchronized (obj) {
if (ticketCount > 0) {
System.out.println(Thread.currentThread().getName() + "买了第" + ticketCount + "张票");
--ticketCount;
} else {
System.out.println("票卖完了");
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
测试类与线程类同上
1.3普通方法上使用synchronized关键字(相当于是锁对象):
售票类:
public class SaleTicket {
private static int ticketCount=100;
public synchronized void saleTicket(){
while (ticketCount > 0){
if (ticketCount > 0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticketCount+"张票");
--ticketCount;
}else {
System.out.println("票卖完了");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试类与线程类同上
2.使用synchroized锁类:
2.1使用synchroized(类名.class)锁类:
public class SaleTicket {
private static int ticketCount=100;
public void saleTicket(){
while (ticketCount>0){
synchronized (SaleTicket.class){
if (ticketCount > 0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticketCount+"张票");
--ticketCount;
}else {
System.out.println("票卖完了");
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
线程类和测试类同上
2.2静态方法上使用synchronized关键字(相当于是锁类):
售票类:
public class SaleTicket {
private static int ticketCount=100;
public static synchronized void saleTicket(){
while (ticketCount > 0){
if (ticketCount > 0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticketCount+"张票");
--ticketCount;
}else {
System.out.println("票卖完了");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程类:
public class TicketThread extends Thread{
private static int ticketCount=100;
@Override
public void run() {
//saleTicket.saleTicket();
SaleTicket.saleTicket();
}
}
测试类:
public static void main(String[] args) {
new TicketThread().start();
new TicketThread().start();
}
关于使用synchronized关键字之后本地模拟出现多线程中只有一个线程完成所有任务的情况,一般是和CPU有关,本场景中可以增到票数.
如有描述不当之处,还望指正,期待发现问题,解决问题!