主要理清锁的使用和本质锁的是什么:
synchronized:
synchronized是java中的一个关键字,在JVM层面上实现的,使用时不需要管理锁的获取和释放。(synchronized发生异常时,会自动释放线程占有的锁)
直接上代码:
public class SynchronziedTest implements Runnable{
//非静态属性
private int num;
//非静态属性,加了volatile关键字(1.该值直接刷新到主存,2.禁止jvm指令重排)
private volatile int count;
////静态属性
private static int other;
//静态属性
private static int changme = 0;
//静态属性,同时加上volatile关键字
private static volatile int sum;
//类的静态属性
private static final Object obj = new Object();
//据说,此锁更可提高性能。源于:锁的对象越小越好
private static byte block[] = {};
//方法上加同步,用的对象锁:锁住的是当前对象,不同对象操作时,线程不安全
public synchronized void addNum(){
num++;
}
//非静态方法中的代码块加同步
public void addCount(){
//锁住的是当前对象的类对象
synchronized (this.getClass()){
count+=2;
}
}
//非静态方法中的代码块加同步,锁的是类的静态成员属性
public void mulCount(){
synchronized (SynchronziedTest.obj){
count-=1;
}
}
//非静态方法中的代码块加同步
public void addOther(){
//锁住的是当前对象的类对象
synchronized (this.getClass()){
other+=2;
}
}
//非静态方法中的代码块加同步,锁的是类的静态成员属性(属性必须被static以及final修饰,否则报错)
public void mulOther(){
synchronized (SynchronziedTest.obj){
other-=1;
}
}
//静态方法加同步,对静态变量进行操作,锁的是当前类对象
public synchronized static void addchangme(){
changme+=5;
}
//静态方法中静态代码块加同步,对静态变量chanme进行操作
public static void mulchangme(){
//同步锁锁住的是该类的静态成员属性
synchronized (SynchronziedTest.block){
for (int i=0;i<2;i++){
changme-=1;
}
}
}
//非静态方法加同步,操作静态属性
public synchronized void sum(){
sum+=10;
}
//非静态方法
public void mulSum(){
//代码块上加同步,操作静态属性
synchronized (SynchronziedTest.class){
for (int i=0;i<3;i++){
sum-=1;
}
}
}
public void printer(){
//计划值为2:实际值为1:,即同步没有生效
System.out.println(Thread.currentThread().getName()+" num值为: " + num);
//计划值为:实际值为1:,即同步没有生效
System.out.println(Thread.currentThread().getName()+" count值为: " + count);
//计划值为2:实际值为2:,即同步生效
System.out.println(Thread.currentThread().getName()+" other值为: " + other);
//计划值为6:实际值为6:,即同步生效
System.out.println(Thread.currentThread().getName()+" changme值为: " + changme);
//计划值为14:实际值为14:,即同步生效
System.out.println(Thread.currentThread().getName()+" sum值为: " + sum);
}
@Override
public void run() {
addNum();
addCount();
mulCount();
addOther();
mulOther();
addchangme();
mulchangme();
sum();
mulSum();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printer();
}
}
public class Test {
public static void main(String[] args) {
Thread t1 = new Thread(new SynchronziedTest(),"线程1");
Thread t2 = new Thread(new SynchronziedTest(),"线程2");
t1.start();
t2.start();
}
}
运行结果:
线程2 num值为: 1
线程2 count值为: 1
线程2 other值为: 2
线程2 changme值为: 6
线程2 sum值为: 14
线程1 num值为: 1
线程1 count值为: 1
线程1 other值为: 2
线程1 changme值为: 6
线程1 sum值为: 14
确保多线程操作的资源是同一资源两种方式:单列(确保同一对象)/static关键字(确保类的同一属性)
Lock:
Lock是一个接口,通过代码实现,使用时候需要手动进行锁的释放,如果没有主动释放,很容易造成死锁(需要在finally块中释放锁)
直接上代码:
public class LockTest implements Runnable{
//非静态属性
private int num;
//非静态属性
private int A;
//非静态属性
private int B;
//非静态属性,加了volatile关键字(1.该值直接刷新到主存,2.禁止jvm指令重排)
private volatile int count;
////静态属性
private static int other;
//静态属性
private static int changme = 0;
//静态属性,同时加上volatile关键字
private static volatile int sum;
//非静态锁
private Lock lock1 = new ReentrantLock();
//静态锁
private static Lock lock2 = new ReentrantLock();
public void addNum(){
Lock lock3 = new ReentrantLock();
lock3.lock();
try {
for (int i = 0;i<5;i++){
num++;
}
}finally {
lock3.unlock();
}
}
public void mulNum(){
Lock lock3 = new ReentrantLock();
lock3.lock();
try {
num--;
}finally {
lock3.unlock();
}
}
public void addCount(){
lock1.lock();
try {
count+=2;
}finally {
lock1.unlock();
}
}
public void mulCount(){
lock1.lock();
try {
count-=1;
}finally {
lock1.unlock();
}
}
public void addOther(){
lock2.lock();
try{
other+=2;
}finally {
lock2.unlock();
}
}
public void mulOther(){
lock2.lock();
try{
other-=1;
}finally {
lock2.unlock();
}
}
public static void addchangme(){
lock2.lock();
try{
changme+=5;
}finally {
lock2.unlock();
}
}
public static void mulchangme(){
lock2.lock();
try{
for (int i=0;i<2;i++){
changme-=1;
}
}finally {
lock2.unlock();
}
}
public void sum(){
lock2.lock();
try{
for (int i=0;i<2;i++){
sum+=10;
}
}finally {
lock2.unlock();
}
}
public void mulSum(){
lock2.lock();
try{
for (int i=0;i<3;i++){
sum-=1;
}
}finally {
lock2.unlock();
}
}
public void addA(){
lock2.lock();
try {
for (int i = 0;i<3;i++){
A++;
}
}finally {
lock2.unlock();
}
}
public void mulA(){
lock2.lock();
try {
A--;
}finally {
lock2.unlock();
}
}
public void addB(){
lock1.lock();
try {
for (int i = 0;i<3;i++){
B++;
}
}finally {
lock1.unlock();
}
}
public void mulB(){
lock1.lock();
try {
B--;
}finally {
lock1.unlock();
}
}
//多线程操作成功同步条件:
//1.使用的全局锁(Lock为类的静态成员属性);
//2.对类的全局变量进行操作(类的静态成员属性);
public void printer(){
//计划值为8:实际值为4:,即同步没有生效
System.out.println(Thread.currentThread().getName()+" num值为: " + num);
//计划值为2:实际值为1:,即同步没有生效
System.out.println(Thread.currentThread().getName()+" count值为: " + count);
//计划值为2:实际值为2:,即同步生效
System.out.println(Thread.currentThread().getName()+" other值为: " + other);
//计划值为6:实际值为6:,即同步生效
System.out.println(Thread.currentThread().getName()+" changme值为: " + changme);
//计划值为34:实际值为34:,即同步生效
System.out.println(Thread.currentThread().getName()+" sum值为: " + sum);
//计划值为4:实际值为2:,即同步不生效
System.out.println(Thread.currentThread().getName()+" A值为: " + A);
//计划值为4:实际值为2:,即同步不生效
System.out.println(Thread.currentThread().getName()+" B值为: " + B);
}
@Override
public void run() {
addNum();
mulNum();
addCount();
mulCount();
addOther();
mulOther();
addchangme();
mulchangme();
sum();
mulSum();
addA();
mulA();
addB();
mulB();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printer();
}
}
public class Test {
public static void main(String[] args) {
Thread t1 = new Thread(new LockTest(),"线程1");
Thread t2 = new Thread(new LockTest(),"线程2");
t1.start();
t2.start();
}
}
线程1 num值为: 4
线程1 count值为: 1
线程1 other值为: 2
线程1 changme值为: 6
线程1 sum值为: 34
线程1 A值为: 2
线程1 B值为: 2
线程2 num值为: 4
线程2 count值为: 1
线程2 other值为: 2
线程2 changme值为: 6
线程2 sum值为: 34
线程2 A值为: 2
线程2 B值为: 2
确保多线程操作的资源是同一资源两种方式:单列/static关键字
结论:
使用同步锁,一定要搞清楚,需要使用类锁,还是对象锁;如果是不同对象多线程操作同一资源情况,要使用类锁;如果是同一个对象多线程操作同一资源时,需要使用对象锁。具体情况采用相应的锁进行同步问题。
文章有误,欢迎指出!