示例代码
public class SyncDemo {
static {
System.loadLibrary( "MyThreadSyncNative" );
}
Object o= new Object();
public static void main(String[] args) throws InterruptedException {
System.out.println("-------------------------");
Thread.sleep(5000);
SyncDemo syncDemo = new SyncDemo();
syncDemo.start();
}
public void start() {
Thread thread = new Thread() {
public void run() {
while (true) {
try {
Thread.sleep(500);
sync();
} catch (InterruptedException e) {
}
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(500);
sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.setName("t1");
// thread2.setName("t2");
thread.start();
// thread2.start();
}
public native void getMytid();
public void sync() throws InterruptedException {
synchronized (o) {
getMytid();//打印了当前线程的id
}
}
}
对于示例代码分析,使用synchronized关键字。如果thread2线程不执行,持有锁将会是偏向锁。thread2运行将会变成重量级锁。
synchronized
synchronized种类:
1、偏向锁 (方法需要保持线程安全,实际情况不一定有互斥,所以偏向锁是synchronzied锁的对象如果没有资源竞争的情况下存在的。 只会调用一次os函数实现)
2、轻量级锁
3、重量级锁(互斥 借助os函数来实现的锁)
java锁的实现对应操作系统函数(在pthread_mutex_lock.c文件)
java锁有关的操作系统相关方法
pthread_mutex_t pthread_mutex_init pthread_mutex_lock pthread_mutex_unlock
linux编译glibc
下面编译glibc是在18.04.1-Ubuntu环境
image.png
下载glibc
http://ftp.gnu.org/gnu/glibc/
首先,查看当前版本(2.27)
ldd --version
安装jdk
apt-get install openjdk-8-jdk
安装gcc make gawk bison
apt-get install gcc -y
apt-get install make gawk bison -y
下载glibc
与之前版本相同的
wget http://ftp.gnu.org/gnu/glibc/glibc-2.27.tar.gz
解压
tar zxvf glibc-2.27.tar.gz
cd glibc-2.27
修改pthread_mutex_lock.c
/root/glibc-2.27/nptl/pthread_mutex_lock.c文件
添加 #include <stdio.h>
fprintf(stderr,"my message tid=%lu\n",pthread_self());
image.png
新建目录
cd /root/glibc-2.27/
mkdir myglib
cd myglib/
编译
../configure --prefix=/usr
(或编译命令../configure --prefix=/usr --disable-profile --enable-add-ons --with-head=/usr/include --with-binutils=/usr/bin)
make
make install
生成so文件
示例代码调用了本地方法getMytid,System.loadLibrary( "MyThreadSyncNative" );调用加载系统库。具体步骤可参考【java线程模型】
由于,我修改了pthread_mutex_lock.c文件。运行java命令
image.png
到这里说明glibc编译成功
证明偏向锁
证明synchronzied偏向锁只会调用一次操作系统函数
根据示例代码测试
image.png
把示例代码中thread2.start();注释去掉,即两个线程运行
image.png
总结:
java对象持有锁与操作系统锁一一对应关系
jvm不推荐(stop()方法)停止一个线程,一定要执行完 。使用interrupt方法
interrupt方法
1、优雅停止线程,资源能够释放。
2、能解阻塞,继续往下执行。
3、可以给isInterrupted赋值
网友评论