并发编程1

并发编程1

编译openjdk源码

  • 怎么看这个方法,在github上下载open jdk方法
  • 为什么下的是jdk11,编译jdk11必须要有jdk8的代码(编译jdk源码,必须在目录下有一个比它版本低的jdk源码)
  • native方法是通过JNI方法调用的,对应于一个c语言方法,hotspot大部分基础功能都通过openjdk开源了

java中的线程和操作系统的线程是什么关系

  • java线程的本质

  • start方法启动后,调用软方法run()

start()源码的线程控制原语

  • start0()是一个native方法,对应于openjdk中的Thread.c(对应于Thread.java),关联到 jvm_startThread()方法

jvm_startThread()在jvm.cpp

  • 实例化一个c++对象 JavaThread
  • MutexLocker()是一个很重要的方法
  • 然后根据操作系统类型,如果是linux,就会调用os_linux.c下面pthread_create()方法
pthread_create()
  • 在os_linux.cpp文件里面

  • int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
    
具体的参数
  • 根据man配置的信息可以得出pthread_create会创建一个线程,这个函数是linux系统的函数,可以用C
    或者C++直接调用,上面信息也告诉程序员这个函数在pthread.h, 这个函数有四个参数,这四个参数由glibC提供

  • pthread_t *thread:传出参数,调用之后会传出被创建
    线程的id,定义 pthread_t pid; 继而 取地址
    &pid

  • const pthread_attr_t
    *attr: 线程属性,关于线程属性是linux
    的知识,一般传NULL,保持默认属性

  • void(start routine)(void *):线程的启动后的主体函数,会回调java线程中的run()方法,需要你定义一个函数,然后传函
    数名即可

  • void *arg:参数,非必须

linux上启动一个线程的代码

  • //头文件
    #include <pthread.h>
    #include <stdio.h>
    //定义一个变量,接受创建线程后的线程id
    pthread_t pid;
    //定义线程的主体函数
    void* thread_entity(void* arg) {
        printf("i am new Thread! from c");
    }
    //main方法,程序入口,main和java的main一样会产生一个进程,继而产生一个main线程
    int main() { 
        //调用操作系统的函数创建线程,注意四个参数 
        pthread_create(&pid,NULL,thread_entity,NULL); 
        //usleep是睡眠的意思,那么这里的睡眠是让谁睡眠呢? 
        //为什么需要睡眠?如果不睡眠会出现什么情况 
        usleep(100); 
        printf("main\n");
    }
    

总结

  • 下载一个clion的idea

  • 为什么下的是jdk11,编译jdk11必须要有jdk8的代码,下载11、12的代码

  • idea中进行debug,配置选项

    • debug argument :com.shadow.app.ThreadDemo
  • 需要把自己编译的类放到虚拟机中的bin目录下

  • debug过程中,会启动很多线程,所以跳过一些断点,才会跳到os_linux.cpp()中的pthread_create()是由自己编译的类实现的

  • aqs比sysnchronized的效率高

    • aqs压根就没有调过c++的代码,除非到park线程的阶段,这样才叫重量锁!而cas这种没有线程切换的过程是轻量锁。
  • 启动过程

    • Thread.start()
    • native Thread.start0()
    • JVM 实例化一个c++对象JavaThread(JVM_ENTRY–宏)
    • 判断os,如果是linux系统,会调用pthread_create()

实现JNI调用

  • package com.shadow.app;
    public class ZLThread {
      //装载库,保证JVM在启动的时候就会装载,故而一般是也给static
     static {
       System.loadLibrary( "EnjoyThreadNative" );
     }
     public static void main(String[] args) {
       ZLThread zLThread =new ZLThread();
       // tnew.c.start1()
       zLThread.start1();
     }
     private native void start1();
    }
    
  • 自定义JNI对应的java代码已经有了,还需要些c语言的代码

启动步骤

  • 1.javah编译一个so文件

    • javah在java9之后就没有了

    • java11之后javac ZLThread.java

      javac -h . ZLThread.java(java11中间有一个点,要注意)

    • 会多一个com_shadow_app_ZLThread.h文件

    • #include<jni.h>
      #ifndef _Included_com_shadow_app_ZLThread
      #define _Included_com_shadow_app_ZLThread
      #ifdef __cplusplus
      extern "C"{
      #endif
      JNIEXPORT void(JNICALL Java_com_shadow_app_ZLThread_start1(JNIEnv *, jobject);
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      
  • 2.需要把上一步生成的.h文件中的方法名复制到自己的.c文件中

    • 本地方法的代码编写( tnew.c文件)

    • #include <pthread.h>
      #include <stdio.h>
      #include "com_shadow_app_ZLThread.h"
      //定义变量接受线程id
      pthread_t pid;
      //线程的主体方法相当于 java当中的run
      void* thread_entity(void* arg) {
        //子线程死循环
        while(1){
          //睡眠100毫秒
          usleep(100);
          //打印
          printf("I am new Thread\n"); 
       }
      }
      //c语言的主方法入口方法,相当于java的main
      JNIEXPORT void(JNICALL Java_com_shadow_app_ZLThread_start1(JNIEnv *, jobject) {
        //调用linux的系统的函数创建一个线程
        pthread_create(&pid,NULL,thread_entity,NULL);
        //主线程死循环
        while(1){
          //睡眠100毫秒
          usleep(100);
          //打印
          printf("I am main\n");
       }
      }
      
  • 3.把.c文件转换成.so文件

    • gcc -fPIC -I /usr/lib/jvm/java-1.8.0-openjdk/include -I /usr/lib/jvm/java-1.8.0-openjdk/include/linux -shared -o libLubanThreadNative.so threadNew.c

    • gcc -fPIC -I /home/shadows/soft/jdk11/include -I /home/shadows/soft/jdk11/include/linux -shared -o libEnjoyThreadNative.so tnew.c

  • 4.需要把.so文件所在目录加到linux需要加载的资源目录中,这样java文件才能找到libEnjoyThreadNative.so文件

    • export LD_LIBRARY_PATH=&LD_LIBRARY_PATH:{libLubanThreadNative.so}

    • export LD_LIBRARY_PATH=&LD_LIBRARY_PATH:/home/shadows/enjoy/com/shadow/app

  • 5.运行java文件

    • java com.shadow.app.ZLThread
    • 启动成功的话,死循环打印I am new Thread和I am main

答疑

1.java中的线程内容是跟操作系统中的线程对应的

2.怎么解决事务补偿

  • 订单->支付-(mq)->发红包->加积分

  • 假设发红包挂掉了,肯定不能回滚,用户钱都没了

  • 等服务起来,去做事务补偿

  • 通过幂等解决(某一个方法有10行,运行了5行,在这里挂掉了,服务恢复后,不能重复前5行)

已标记关键词 清除标记
相关推荐
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页